ast: Keep style consistent

Methods and functions are `CamelCase()`
Public fields are `snake_case` with no trailing `_`
Private fields are `snake_case` with a trailing `_`

Remove pointless getters on fully immutable fields.
They provide no value, and just add `()` noise on use.

Remove unused methods.

Bug: tint:1231
Change-Id: If32efd039df48938efd5bc2186d51fe4853e9840
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/66600
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/fuzzers/tint_ast_fuzzer/mutations/replace_identifier.cc b/fuzzers/tint_ast_fuzzer/mutations/replace_identifier.cc
index 2b2bb9d..6823d21 100644
--- a/fuzzers/tint_ast_fuzzer/mutations/replace_identifier.cc
+++ b/fuzzers/tint_ast_fuzzer/mutations/replace_identifier.cc
@@ -89,8 +89,8 @@
       tint::As<ast::Variable>(node_id_map.GetNode(message_.replacement_id()));
 
   auto* cloned_replacement =
-      clone_context->dst->Expr(clone_context->Clone(use_node->source()),
-                               clone_context->Clone(replacement_var->symbol()));
+      clone_context->dst->Expr(clone_context->Clone(use_node->source),
+                               clone_context->Clone(replacement_var->symbol));
   clone_context->Replace(use_node, cloned_replacement);
   new_node_id_map->Add(cloned_replacement, message_.use_id());
 }
diff --git a/fuzzers/tint_ast_fuzzer/mutations/replace_identifier_test.cc b/fuzzers/tint_ast_fuzzer/mutations/replace_identifier_test.cc
index bf12407..d3a125f 100644
--- a/fuzzers/tint_ast_fuzzer/mutations/replace_identifier_test.cc
+++ b/fuzzers/tint_ast_fuzzer/mutations/replace_identifier_test.cc
@@ -49,19 +49,18 @@
 
   NodeIdMap node_id_map(program);
 
-  const auto& main_fn_stmts =
-      program.AST().Functions()[0]->body()->statements();
+  const auto& main_fn_stmts = program.AST().Functions()[0]->body->statements;
 
   const auto* a_var =
-      main_fn_stmts[0]->As<ast::VariableDeclStatement>()->variable();
+      main_fn_stmts[0]->As<ast::VariableDeclStatement>()->variable;
   ASSERT_NE(a_var, nullptr);
 
   const auto* b_var =
-      main_fn_stmts[2]->As<ast::VariableDeclStatement>()->variable();
+      main_fn_stmts[2]->As<ast::VariableDeclStatement>()->variable;
   ASSERT_NE(b_var, nullptr);
 
   const auto* e_var =
-      main_fn_stmts[4]->As<ast::VariableDeclStatement>()->variable();
+      main_fn_stmts[4]->As<ast::VariableDeclStatement>()->variable;
   ASSERT_NE(e_var, nullptr);
 
   auto a_var_id = node_id_map.GetId(a_var);
@@ -70,10 +69,10 @@
   auto b_var_id = node_id_map.GetId(b_var);
   ASSERT_NE(b_var_id, 0);
 
-  const auto* sum_expr = b_var->constructor()->As<ast::BinaryExpression>();
+  const auto* sum_expr = b_var->constructor->As<ast::BinaryExpression>();
   ASSERT_NE(sum_expr, nullptr);
 
-  auto a_ident_id = node_id_map.GetId(sum_expr->lhs());
+  auto a_ident_id = node_id_map.GetId(sum_expr->lhs);
   ASSERT_NE(a_ident_id, 0);
 
   auto sum_expr_id = node_id_map.GetId(sum_expr);
@@ -83,7 +82,7 @@
   ASSERT_NE(e_var_id, 0);
 
   auto vec_member_access_id = node_id_map.GetId(
-      e_var->constructor()->As<ast::MemberAccessorExpression>()->member());
+      e_var->constructor->As<ast::MemberAccessorExpression>()->member);
   ASSERT_NE(vec_member_access_id, 0);
 
   // use_id is invalid.
@@ -136,10 +135,9 @@
 
   auto use_id = node_id_map.GetId(program.AST()
                                       .Functions()[0]
-                                      ->body()
-                                      ->statements()[0]
+                                      ->body->statements[0]
                                       ->As<ast::AssignmentStatement>()
-                                      ->lhs());
+                                      ->lhs);
   ASSERT_NE(use_id, 0);
 
   auto replacement_id = node_id_map.GetId(program.AST().GlobalVariables()[1]);
@@ -170,14 +168,11 @@
 
   auto use_id = node_id_map.GetId(program.AST()
                                       .Functions()[0]
-                                      ->body()
-                                      ->statements()[0]
+                                      ->body->statements[0]
                                       ->As<ast::AssignmentStatement>()
-                                      ->lhs()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+                                      ->lhs->As<ast::UnaryOpExpression>()
+                                      ->expr->As<ast::UnaryOpExpression>()
+                                      ->expr);
   ASSERT_NE(use_id, 0);
 
   ASSERT_FALSE(MutationReplaceIdentifier(use_id, replacement_id)
@@ -202,22 +197,18 @@
 
   auto replacement_id = node_id_map.GetId(program.AST()
                                               .Functions()[0]
-                                              ->body()
-                                              ->statements()[0]
+                                              ->body->statements[0]
                                               ->As<ast::VariableDeclStatement>()
-                                              ->variable());
+                                              ->variable);
   ASSERT_NE(replacement_id, 0);
 
   auto use_id = node_id_map.GetId(program.AST()
                                       .Functions()[0]
-                                      ->body()
-                                      ->statements()[1]
+                                      ->body->statements[1]
                                       ->As<ast::AssignmentStatement>()
-                                      ->lhs()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+                                      ->lhs->As<ast::UnaryOpExpression>()
+                                      ->expr->As<ast::UnaryOpExpression>()
+                                      ->expr);
   ASSERT_NE(use_id, 0);
 
   ASSERT_FALSE(MutationReplaceIdentifier(use_id, replacement_id)
@@ -242,22 +233,18 @@
 
   auto replacement_id = node_id_map.GetId(program.AST()
                                               .Functions()[0]
-                                              ->body()
-                                              ->statements()[0]
+                                              ->body->statements[0]
                                               ->As<ast::VariableDeclStatement>()
-                                              ->variable());
+                                              ->variable);
   ASSERT_NE(replacement_id, 0);
 
   auto use_id = node_id_map.GetId(program.AST()
                                       .Functions()[0]
-                                      ->body()
-                                      ->statements()[1]
+                                      ->body->statements[1]
                                       ->As<ast::AssignmentStatement>()
-                                      ->lhs()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+                                      ->lhs->As<ast::UnaryOpExpression>()
+                                      ->expr->As<ast::UnaryOpExpression>()
+                                      ->expr);
   ASSERT_NE(use_id, 0);
 
   ASSERT_FALSE(MutationReplaceIdentifier(use_id, replacement_id)
@@ -280,19 +267,16 @@
   NodeIdMap node_id_map(program);
 
   auto replacement_id =
-      node_id_map.GetId(program.AST().Functions()[0]->params()[0]);
+      node_id_map.GetId(program.AST().Functions()[0]->params[0]);
   ASSERT_NE(replacement_id, 0);
 
   auto use_id = node_id_map.GetId(program.AST()
                                       .Functions()[0]
-                                      ->body()
-                                      ->statements()[0]
+                                      ->body->statements[0]
                                       ->As<ast::AssignmentStatement>()
-                                      ->lhs()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+                                      ->lhs->As<ast::UnaryOpExpression>()
+                                      ->expr->As<ast::UnaryOpExpression>()
+                                      ->expr);
   ASSERT_NE(use_id, 0);
 
   ASSERT_FALSE(MutationReplaceIdentifier(use_id, replacement_id)
@@ -325,14 +309,11 @@
 
   auto use_id = node_id_map.GetId(program.AST()
                                       .Functions()[0]
-                                      ->body()
-                                      ->statements()[0]
+                                      ->body->statements[0]
                                       ->As<ast::AssignmentStatement>()
-                                      ->lhs()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+                                      ->lhs->As<ast::UnaryOpExpression>()
+                                      ->expr->As<ast::UnaryOpExpression>()
+                                      ->expr);
   ASSERT_NE(use_id, 0);
 
   ASSERT_FALSE(MutationReplaceIdentifier(use_id, replacement_id)
@@ -365,12 +346,10 @@
 
   auto use_id = node_id_map.GetId(program.AST()
                                       .Functions()[0]
-                                      ->body()
-                                      ->statements()[1]
+                                      ->body->statements[1]
                                       ->As<ast::AssignmentStatement>()
-                                      ->rhs()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+                                      ->rhs->As<ast::UnaryOpExpression>()
+                                      ->expr);
   ASSERT_NE(use_id, 0);
 
   ASSERT_FALSE(MutationReplaceIdentifier(use_id, replacement_id)
@@ -405,12 +384,10 @@
 
   auto use_id = node_id_map.GetId(program.AST()
                                       .Functions()[0]
-                                      ->body()
-                                      ->statements()[1]
+                                      ->body->statements[1]
                                       ->As<ast::AssignmentStatement>()
-                                      ->rhs()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+                                      ->rhs->As<ast::UnaryOpExpression>()
+                                      ->expr);
   ASSERT_NE(use_id, 0);
 
   ASSERT_FALSE(MutationReplaceIdentifier(use_id, replacement_id)
@@ -443,14 +420,11 @@
 
   auto use_id = node_id_map.GetId(program.AST()
                                       .Functions()[0]
-                                      ->body()
-                                      ->statements()[0]
+                                      ->body->statements[0]
                                       ->As<ast::AssignmentStatement>()
-                                      ->rhs()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+                                      ->rhs->As<ast::UnaryOpExpression>()
+                                      ->expr->As<ast::UnaryOpExpression>()
+                                      ->expr);
   ASSERT_NE(use_id, 0);
 
   ASSERT_FALSE(MutationReplaceIdentifier(use_id, replacement_id)
@@ -483,14 +457,11 @@
 
   auto use_id = node_id_map.GetId(program.AST()
                                       .Functions()[0]
-                                      ->body()
-                                      ->statements()[0]
+                                      ->body->statements[0]
                                       ->As<ast::AssignmentStatement>()
-                                      ->rhs()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+                                      ->rhs->As<ast::UnaryOpExpression>()
+                                      ->expr->As<ast::UnaryOpExpression>()
+                                      ->expr);
   ASSERT_NE(use_id, 0);
 
   ASSERT_FALSE(MutationReplaceIdentifier(use_id, replacement_id)
@@ -514,24 +485,19 @@
 
   auto use_id = node_id_map.GetId(program.AST()
                                       .Functions()[0]
-                                      ->body()
-                                      ->statements()[2]
+                                      ->body->statements[2]
                                       ->As<ast::AssignmentStatement>()
-                                      ->lhs()
-                                      ->As<ast::ArrayAccessorExpression>()
-                                      ->array()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+                                      ->lhs->As<ast::ArrayAccessorExpression>()
+                                      ->array->As<ast::UnaryOpExpression>()
+                                      ->expr->As<ast::UnaryOpExpression>()
+                                      ->expr);
   ASSERT_NE(use_id, 0);
 
   auto replacement_id = node_id_map.GetId(program.AST()
                                               .Functions()[0]
-                                              ->body()
-                                              ->statements()[0]
+                                              ->body->statements[0]
                                               ->As<ast::VariableDeclStatement>()
-                                              ->variable());
+                                              ->variable);
   ASSERT_NE(replacement_id, 0);
 
   ASSERT_TRUE(MaybeApplyMutation(
@@ -569,18 +535,15 @@
 
   auto use_id = node_id_map.GetId(program.AST()
                                       .Functions()[0]
-                                      ->body()
-                                      ->statements()[2]
+                                      ->body->statements[2]
                                       ->As<ast::AssignmentStatement>()
-                                      ->lhs()
-                                      ->As<ast::ArrayAccessorExpression>()
-                                      ->array()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+                                      ->lhs->As<ast::ArrayAccessorExpression>()
+                                      ->array->As<ast::UnaryOpExpression>()
+                                      ->expr);
   ASSERT_NE(use_id, 0);
 
   auto replacement_id =
-      node_id_map.GetId(program.AST().Functions()[0]->params()[0]);
+      node_id_map.GetId(program.AST().Functions()[0]->params[0]);
   ASSERT_NE(replacement_id, 0);
 
   ASSERT_TRUE(MaybeApplyMutation(
@@ -619,16 +582,12 @@
 
   auto use_id = node_id_map.GetId(program.AST()
                                       .Functions()[0]
-                                      ->body()
-                                      ->statements()[1]
+                                      ->body->statements[1]
                                       ->As<ast::AssignmentStatement>()
-                                      ->lhs()
-                                      ->As<ast::ArrayAccessorExpression>()
-                                      ->array()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+                                      ->lhs->As<ast::ArrayAccessorExpression>()
+                                      ->array->As<ast::UnaryOpExpression>()
+                                      ->expr->As<ast::UnaryOpExpression>()
+                                      ->expr);
   ASSERT_NE(use_id, 0);
 
   auto replacement_id = node_id_map.GetId(program.AST().GlobalVariables()[0]);
@@ -654,19 +613,15 @@
 
   NodeIdMap node_id_map(program);
 
-  auto use_id = node_id_map.GetId(program.AST()
-                                      .Functions()[0]
-                                      ->body()
-                                      ->statements()[1]
-                                      ->As<ast::VariableDeclStatement>()
-                                      ->variable()
-                                      ->constructor()
-                                      ->As<ast::ArrayAccessorExpression>()
-                                      ->array()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+  auto use_id = node_id_map.GetId(
+      program.AST()
+          .Functions()[0]
+          ->body->statements[1]
+          ->As<ast::VariableDeclStatement>()
+          ->variable->constructor->As<ast::ArrayAccessorExpression>()
+          ->array->As<ast::UnaryOpExpression>()
+          ->expr->As<ast::UnaryOpExpression>()
+          ->expr);
   ASSERT_NE(use_id, 0);
 
   auto replacement_id = node_id_map.GetId(program.AST().GlobalVariables()[0]);
@@ -694,25 +649,21 @@
 
   NodeIdMap node_id_map(program);
 
-  auto use_id = node_id_map.GetId(program.AST()
-                                      .Functions()[0]
-                                      ->body()
-                                      ->statements()[3]
-                                      ->As<ast::VariableDeclStatement>()
-                                      ->variable()
-                                      ->constructor()
-                                      ->As<ast::ArrayAccessorExpression>()
-                                      ->array()
-                                      ->As<ast::UnaryOpExpression>()
-                                      ->expr());
+  auto use_id = node_id_map.GetId(
+      program.AST()
+          .Functions()[0]
+          ->body->statements[3]
+          ->As<ast::VariableDeclStatement>()
+          ->variable->constructor->As<ast::ArrayAccessorExpression>()
+          ->array->As<ast::UnaryOpExpression>()
+          ->expr);
   ASSERT_NE(use_id, 0);
 
   auto replacement_id = node_id_map.GetId(program.AST()
                                               .Functions()[0]
-                                              ->body()
-                                              ->statements()[2]
+                                              ->body->statements[2]
                                               ->As<ast::VariableDeclStatement>()
-                                              ->variable());
+                                              ->variable);
   ASSERT_NE(replacement_id, 0);
   ASSERT_FALSE(MutationReplaceIdentifier(use_id, replacement_id)
                    .IsApplicable(program, node_id_map));
diff --git a/fuzzers/tint_ast_fuzzer/util.h b/fuzzers/tint_ast_fuzzer/util.h
index d851511..e82ebcc 100644
--- a/fuzzers/tint_ast_fuzzer/util.h
+++ b/fuzzers/tint_ast_fuzzer/util.h
@@ -54,7 +54,7 @@
   // Walk up the hierarchy of blocks in which `curr_stmt` is contained.
   for (const auto* block = curr_stmt->Block(); block;
        block = tint::As<sem::BlockStatement>(block->Parent())) {
-    for (const auto* stmt : *block->Declaration()) {
+    for (const auto* stmt : block->Declaration()->statements) {
       if (stmt == curr_stmt->Declaration()) {
         // `curr_stmt` was found. This is only possible if `block is the
         // enclosing block of `curr_stmt` since the AST nodes are not shared.
@@ -65,7 +65,7 @@
       }
 
       if (const auto* var_node = tint::As<ast::VariableDeclStatement>(stmt)) {
-        const auto* sem_var = program.Sem().Get(var_node->variable());
+        const auto* sem_var = program.Sem().Get(var_node->variable);
         if (pred(sem_var)) {
           result.push_back(sem_var);
         }
@@ -74,7 +74,7 @@
   }
 
   // Process function parameters.
-  for (const auto* param : curr_stmt->Function()->params()) {
+  for (const auto* param : curr_stmt->Function()->params) {
     const auto* sem_var = program.Sem().Get(param);
     if (pred(sem_var)) {
       result.push_back(sem_var);
diff --git a/src/ast/alias.cc b/src/ast/alias.cc
index 8a8bba8..a6983e1 100644
--- a/src/ast/alias.cc
+++ b/src/ast/alias.cc
@@ -21,12 +21,9 @@
 namespace tint {
 namespace ast {
 
-Alias::Alias(ProgramID program_id,
-             const Source& source,
-             const Symbol& name,
-             Type* subtype)
-    : Base(program_id, source, name), subtype_(subtype) {
-  TINT_ASSERT(AST, subtype_);
+Alias::Alias(ProgramID pid, const Source& src, const Symbol& n, Type* subtype)
+    : Base(pid, src, n), type(subtype) {
+  TINT_ASSERT(AST, type);
 }
 
 Alias::Alias(Alias&&) = default;
@@ -35,9 +32,9 @@
 
 Alias* Alias::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto sym = ctx->Clone(name());
-  auto* ty = ctx->Clone(type());
+  auto src = ctx->Clone(source);
+  auto sym = ctx->Clone(name);
+  auto* ty = ctx->Clone(type);
   return ctx->dst->create<Alias>(src, sym, ty);
 }
 
diff --git a/src/ast/alias.h b/src/ast/alias.h
index 9ca50b8..7f8acdb 100644
--- a/src/ast/alias.h
+++ b/src/ast/alias.h
@@ -26,32 +26,23 @@
 class Alias : public Castable<Alias, TypeDecl> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param name the symbol for the alias
   /// @param subtype the alias'd type
-  Alias(ProgramID program_id,
-        const Source& source,
-        const Symbol& name,
-        Type* subtype);
+  Alias(ProgramID pid, const Source& src, const Symbol& name, Type* subtype);
   /// Move constructor
   Alias(Alias&&);
   /// Destructor
   ~Alias() override;
 
-  /// [DEPRECATED] use name()
-  /// @returns the alias symbol
-  Symbol symbol() const { return name(); }
-  /// @returns the alias type
-  Type* type() const { return subtype_; }
-
   /// Clones this type and all transitive types using the `CloneContext` `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned type
   Alias* Clone(CloneContext* ctx) const override;
 
- private:
-  Type* const subtype_;
+  /// the alias type
+  Type* const type;
 };
 
 }  // namespace ast
diff --git a/src/ast/alias_test.cc b/src/ast/alias_test.cc
index 8a744cf..4e72967 100644
--- a/src/ast/alias_test.cc
+++ b/src/ast/alias_test.cc
@@ -36,8 +36,8 @@
 TEST_F(AstAliasTest, Create) {
   auto* u32 = create<U32>();
   auto* a = Alias("a_type", u32);
-  EXPECT_EQ(a->symbol(), Symbol(1, ID()));
-  EXPECT_EQ(a->type(), u32);
+  EXPECT_EQ(a->name, Symbol(1, ID()));
+  EXPECT_EQ(a->type, u32);
 }
 
 }  // namespace
diff --git a/src/ast/array.cc b/src/ast/array.cc
index b9993a5..c582805 100644
--- a/src/ast/array.cc
+++ b/src/ast/array.cc
@@ -29,14 +29,14 @@
                              const SymbolTable* symbols = nullptr) {
   if (auto* ident = size->As<ast::IdentifierExpression>()) {
     if (symbols) {
-      return symbols->NameFor(ident->symbol());
+      return symbols->NameFor(ident->symbol);
     }
     return "<unknown>";
   }
   if (auto* scalar = size->As<ast::ScalarConstructorExpression>()) {
-    auto* literal = scalar->literal()->As<ast::IntLiteral>();
+    auto* literal = scalar->literal->As<ast::IntLiteral>();
     if (literal) {
-      return std::to_string(literal->value_as_u32());
+      return std::to_string(literal->ValueAsU32());
     }
   }
   // This will never be exposed to the user as the Resolver will reject this
@@ -45,15 +45,12 @@
 }
 }  // namespace
 
-Array::Array(ProgramID program_id,
-             const Source& source,
+Array::Array(ProgramID pid,
+             const Source& src,
              Type* subtype,
-             ast::Expression* size,
-             ast::DecorationList decorations)
-    : Base(program_id, source),
-      subtype_(subtype),
-      size_(size),
-      decos_(decorations) {}
+             ast::Expression* cnt,
+             ast::DecorationList decos)
+    : Base(pid, src), type(subtype), count(cnt), decorations(decos) {}
 
 Array::Array(Array&&) = default;
 
@@ -61,14 +58,14 @@
 
 std::string Array::FriendlyName(const SymbolTable& symbols) const {
   std::ostringstream out;
-  for (auto* deco : decos_) {
+  for (auto* deco : decorations) {
     if (auto* stride = deco->As<ast::StrideDecoration>()) {
-      out << "[[stride(" << stride->stride() << ")]] ";
+      out << "[[stride(" << stride->stride << ")]] ";
     }
   }
-  out << "array<" << subtype_->FriendlyName(symbols);
+  out << "array<" << type->FriendlyName(symbols);
   if (!IsRuntimeArray()) {
-    out << ", " << SizeExprToString(size_, &symbols);
+    out << ", " << SizeExprToString(count, &symbols);
   }
   out << ">";
   return out.str();
@@ -76,11 +73,11 @@
 
 Array* Array::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* ty = ctx->Clone(type());
-  auto* size = ctx->Clone(Size());
-  auto decos = ctx->Clone(decorations());
-  return ctx->dst->create<Array>(src, ty, size, decos);
+  auto src = ctx->Clone(source);
+  auto* ty = ctx->Clone(type);
+  auto* cnt = ctx->Clone(count);
+  auto decos = ctx->Clone(decorations);
+  return ctx->dst->create<Array>(src, ty, cnt, decos);
 }
 
 }  // namespace ast
diff --git a/src/ast/array.h b/src/ast/array.h
index df0ba88..28d8682 100644
--- a/src/ast/array.h
+++ b/src/ast/array.h
@@ -30,16 +30,16 @@
 class Array : public Castable<Array, Type> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param subtype the type of the array elements
-  /// @param size the number of elements in the array. nullptr represents a
+  /// @param count the number of elements in the array. nullptr represents a
   /// runtime-sized array.
   /// @param decorations the array decorations
-  Array(ProgramID program_id,
-        const Source& source,
+  Array(ProgramID pid,
+        const Source& src,
         Type* subtype,
-        ast::Expression* size,
+        ast::Expression* count,
         ast::DecorationList decorations);
   /// Move constructor
   Array(Array&&);
@@ -47,16 +47,7 @@
 
   /// @returns true if this is a runtime array.
   /// i.e. the size is determined at runtime
-  bool IsRuntimeArray() const { return size_ == nullptr; }
-
-  /// @returns the array decorations
-  const ast::DecorationList& decorations() const { return decos_; }
-
-  /// @returns the array type
-  Type* type() const { return subtype_; }
-
-  /// @returns the array size, or nullptr for a runtime array
-  ast::Expression* Size() const { return size_; }
+  bool IsRuntimeArray() const { return count == nullptr; }
 
   /// @param symbols the program's symbol table
   /// @returns the name for this type that closely resembles how it would be
@@ -68,10 +59,14 @@
   /// @return the newly cloned type
   Array* Clone(CloneContext* ctx) const override;
 
- private:
-  Type* const subtype_;
-  ast::Expression* const size_;
-  ast::DecorationList const decos_;
+  /// the array element type
+  Type* const type;
+
+  /// the array size in elements, or nullptr for a runtime array
+  ast::Expression* const count;
+
+  /// the array decorations
+  ast::DecorationList const decorations;
 };
 
 }  // namespace ast
diff --git a/src/ast/array_accessor_expression.cc b/src/ast/array_accessor_expression.cc
index b7b9a41..1f40234 100644
--- a/src/ast/array_accessor_expression.cc
+++ b/src/ast/array_accessor_expression.cc
@@ -21,15 +21,15 @@
 namespace tint {
 namespace ast {
 
-ArrayAccessorExpression::ArrayAccessorExpression(ProgramID program_id,
-                                                 const Source& source,
-                                                 Expression* array,
-                                                 Expression* idx_expr)
-    : Base(program_id, source), array_(array), idx_expr_(idx_expr) {
-  TINT_ASSERT(AST, array_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, array_, program_id);
-  TINT_ASSERT(AST, idx_expr_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, idx_expr_, program_id);
+ArrayAccessorExpression::ArrayAccessorExpression(ProgramID pid,
+                                                 const Source& src,
+                                                 Expression* arr,
+                                                 Expression* idx)
+    : Base(pid, src), array(arr), index(idx) {
+  TINT_ASSERT(AST, array);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, array, program_id);
+  TINT_ASSERT(AST, idx);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, idx, program_id);
 }
 
 ArrayAccessorExpression::ArrayAccessorExpression(ArrayAccessorExpression&&) =
@@ -40,9 +40,9 @@
 ArrayAccessorExpression* ArrayAccessorExpression::Clone(
     CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* arr = ctx->Clone(array_);
-  auto* idx = ctx->Clone(idx_expr_);
+  auto src = ctx->Clone(source);
+  auto* arr = ctx->Clone(array);
+  auto* idx = ctx->Clone(index);
   return ctx->dst->create<ArrayAccessorExpression>(src, arr, idx);
 }
 
diff --git a/src/ast/array_accessor_expression.h b/src/ast/array_accessor_expression.h
index 891884d..fb5e5bc 100644
--- a/src/ast/array_accessor_expression.h
+++ b/src/ast/array_accessor_expression.h
@@ -27,33 +27,30 @@
   /// Constructor
   /// @param program_id the identifier of the program that owns this node
   /// @param source the array accessor source
-  /// @param array the array
-  /// @param idx_expr the index expression
+  /// @param arr the array
+  /// @param idx the index expression
   ArrayAccessorExpression(ProgramID program_id,
                           const Source& source,
-                          Expression* array,
-                          Expression* idx_expr);
+                          Expression* arr,
+                          Expression* idx);
   /// Move constructor
   ArrayAccessorExpression(ArrayAccessorExpression&&);
   ~ArrayAccessorExpression() override;
 
-  /// @returns the array
-  Expression* array() const { return array_; }
-
-  /// @returns the index expression
-  Expression* idx_expr() const { return idx_expr_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   ArrayAccessorExpression* Clone(CloneContext* ctx) const override;
 
+  /// the array
+  Expression* const array;
+
+  /// the index expression
+  Expression* const index;
+
  private:
   ArrayAccessorExpression(const ArrayAccessorExpression&) = delete;
-
-  Expression* const array_;
-  Expression* const idx_expr_;
 };
 
 }  // namespace ast
diff --git a/src/ast/array_accessor_expression_test.cc b/src/ast/array_accessor_expression_test.cc
index 90f93ac..93f374a 100644
--- a/src/ast/array_accessor_expression_test.cc
+++ b/src/ast/array_accessor_expression_test.cc
@@ -26,8 +26,8 @@
   auto* idx = Expr("idx");
 
   auto* exp = create<ArrayAccessorExpression>(ary, idx);
-  ASSERT_EQ(exp->array(), ary);
-  ASSERT_EQ(exp->idx_expr(), idx);
+  ASSERT_EQ(exp->array, ary);
+  ASSERT_EQ(exp->index, idx);
 }
 
 TEST_F(ArrayAccessorExpressionTest, CreateWithSource) {
@@ -36,7 +36,7 @@
 
   auto* exp = create<ArrayAccessorExpression>(Source{Source::Location{20, 2}},
                                               ary, idx);
-  auto src = exp->source();
+  auto src = exp->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/array_test.cc b/src/ast/array_test.cc
index 8bea47b..3ada2c7 100644
--- a/src/ast/array_test.cc
+++ b/src/ast/array_test.cc
@@ -24,10 +24,10 @@
 
 TEST_F(AstArrayTest, CreateSizedArray) {
   auto* u32 = create<U32>();
-  auto* size = Expr(3);
-  auto* arr = create<Array>(u32, size, DecorationList{});
-  EXPECT_EQ(arr->type(), u32);
-  EXPECT_EQ(arr->Size(), size);
+  auto* count = Expr(3);
+  auto* arr = create<Array>(u32, count, DecorationList{});
+  EXPECT_EQ(arr->type, u32);
+  EXPECT_EQ(arr->count, count);
   EXPECT_TRUE(arr->Is<Array>());
   EXPECT_FALSE(arr->IsRuntimeArray());
 }
@@ -35,8 +35,8 @@
 TEST_F(AstArrayTest, CreateRuntimeArray) {
   auto* u32 = create<U32>();
   auto* arr = create<Array>(u32, nullptr, DecorationList{});
-  EXPECT_EQ(arr->type(), u32);
-  EXPECT_EQ(arr->Size(), nullptr);
+  EXPECT_EQ(arr->type, u32);
+  EXPECT_EQ(arr->count, nullptr);
   EXPECT_TRUE(arr->Is<Array>());
   EXPECT_TRUE(arr->IsRuntimeArray());
 }
diff --git a/src/ast/assignment_statement.cc b/src/ast/assignment_statement.cc
index 5569a70..0031bf6 100644
--- a/src/ast/assignment_statement.cc
+++ b/src/ast/assignment_statement.cc
@@ -21,15 +21,15 @@
 namespace tint {
 namespace ast {
 
-AssignmentStatement::AssignmentStatement(ProgramID program_id,
-                                         const Source& source,
-                                         Expression* lhs,
-                                         Expression* rhs)
-    : Base(program_id, source), lhs_(lhs), rhs_(rhs) {
-  TINT_ASSERT(AST, lhs_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs_, program_id);
-  TINT_ASSERT(AST, rhs_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, rhs_, program_id);
+AssignmentStatement::AssignmentStatement(ProgramID pid,
+                                         const Source& src,
+                                         Expression* l,
+                                         Expression* r)
+    : Base(pid, src), lhs(l), rhs(r) {
+  TINT_ASSERT(AST, lhs);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs, program_id);
+  TINT_ASSERT(AST, rhs);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, rhs, program_id);
 }
 
 AssignmentStatement::AssignmentStatement(AssignmentStatement&&) = default;
@@ -38,9 +38,9 @@
 
 AssignmentStatement* AssignmentStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* l = ctx->Clone(lhs_);
-  auto* r = ctx->Clone(rhs_);
+  auto src = ctx->Clone(source);
+  auto* l = ctx->Clone(lhs);
+  auto* r = ctx->Clone(rhs);
   return ctx->dst->create<AssignmentStatement>(src, l, r);
 }
 
diff --git a/src/ast/assignment_statement.h b/src/ast/assignment_statement.h
index 6857a05..bb8ea25 100644
--- a/src/ast/assignment_statement.h
+++ b/src/ast/assignment_statement.h
@@ -37,22 +37,20 @@
   AssignmentStatement(AssignmentStatement&&);
   ~AssignmentStatement() override;
 
-  /// @returns the left side expression
-  Expression* lhs() const { return lhs_; }
-  /// @returns the right side expression
-  Expression* rhs() const { return rhs_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   AssignmentStatement* Clone(CloneContext* ctx) const override;
 
+  /// left side expression
+  Expression* const lhs;
+
+  /// right side expression
+  Expression* const rhs;
+
  private:
   AssignmentStatement(const AssignmentStatement&) = delete;
-
-  Expression* const lhs_;
-  Expression* const rhs_;
 };
 
 }  // namespace ast
diff --git a/src/ast/assignment_statement_test.cc b/src/ast/assignment_statement_test.cc
index 677f0bc..6c1a716 100644
--- a/src/ast/assignment_statement_test.cc
+++ b/src/ast/assignment_statement_test.cc
@@ -28,8 +28,8 @@
   auto* rhs = Expr("rhs");
 
   auto* stmt = create<AssignmentStatement>(lhs, rhs);
-  EXPECT_EQ(stmt->lhs(), lhs);
-  EXPECT_EQ(stmt->rhs(), rhs);
+  EXPECT_EQ(stmt->lhs, lhs);
+  EXPECT_EQ(stmt->rhs, rhs);
 }
 
 TEST_F(AssignmentStatementTest, CreationWithSource) {
@@ -38,7 +38,7 @@
 
   auto* stmt =
       create<AssignmentStatement>(Source{Source::Location{20, 2}}, lhs, rhs);
-  auto src = stmt->source();
+  auto src = stmt->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/ast_type.cc b/src/ast/ast_type.cc
index d48d66d..cd6d4bb 100644
--- a/src/ast/ast_type.cc
+++ b/src/ast/ast_type.cc
@@ -31,8 +31,7 @@
 namespace tint {
 namespace ast {
 
-Type::Type(ProgramID program_id, const Source& source)
-    : Base(program_id, source) {}
+Type::Type(ProgramID pid, const Source& src) : Base(pid, src) {}
 
 Type::Type(Type&&) = default;
 
diff --git a/src/ast/atomic.cc b/src/ast/atomic.cc
index 7ecd74d..635e758 100644
--- a/src/ast/atomic.cc
+++ b/src/ast/atomic.cc
@@ -21,12 +21,12 @@
 namespace tint {
 namespace ast {
 
-Atomic::Atomic(ProgramID program_id, const Source& source, Type* const subtype)
-    : Base(program_id, source), subtype_(subtype) {}
+Atomic::Atomic(ProgramID pid, const Source& src, Type* const subtype)
+    : Base(pid, src), type(subtype) {}
 
 std::string Atomic::FriendlyName(const SymbolTable& symbols) const {
   std::ostringstream out;
-  out << "atomic<" << subtype_->FriendlyName(symbols) << ">";
+  out << "atomic<" << type->FriendlyName(symbols) << ">";
   return out.str();
 }
 
@@ -36,8 +36,8 @@
 
 Atomic* Atomic::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* ty = ctx->Clone(type());
+  auto src = ctx->Clone(source);
+  auto* ty = ctx->Clone(const_cast<Type*>(type));
   return ctx->dst->create<Atomic>(src, ty);
 }
 
diff --git a/src/ast/atomic.h b/src/ast/atomic.h
index 8488ee6..f00d128 100644
--- a/src/ast/atomic.h
+++ b/src/ast/atomic.h
@@ -26,17 +26,14 @@
 class Atomic : public Castable<Atomic, Type> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param subtype the pointee type
-  Atomic(ProgramID program_id, const Source& source, Type* const subtype);
+  Atomic(ProgramID pid, const Source& src, Type* const subtype);
   /// Move constructor
   Atomic(Atomic&&);
   ~Atomic() override;
 
-  /// @returns the pointee type
-  Type* type() const { return const_cast<Type*>(subtype_); }
-
   /// @param symbols the program's symbol table
   /// @returns the name for this type that closely resembles how it would be
   /// declared in WGSL.
@@ -47,8 +44,8 @@
   /// @return the newly cloned type
   Atomic* Clone(CloneContext* ctx) const override;
 
- private:
-  Type const* const subtype_;
+  /// the pointee type
+  Type const* const type;
 };
 
 }  // namespace ast
diff --git a/src/ast/atomic_test.cc b/src/ast/atomic_test.cc
index 33ffaae..9618827 100644
--- a/src/ast/atomic_test.cc
+++ b/src/ast/atomic_test.cc
@@ -26,7 +26,7 @@
 TEST_F(AstAtomicTest, Creation) {
   auto* i32 = create<I32>();
   auto* p = create<Atomic>(i32);
-  EXPECT_EQ(p->type(), i32);
+  EXPECT_EQ(p->type, i32);
 }
 
 TEST_F(AstAtomicTest, FriendlyName) {
diff --git a/src/ast/binary_expression.cc b/src/ast/binary_expression.cc
index c5fb860..f757bfe 100644
--- a/src/ast/binary_expression.cc
+++ b/src/ast/binary_expression.cc
@@ -21,17 +21,17 @@
 namespace tint {
 namespace ast {
 
-BinaryExpression::BinaryExpression(ProgramID program_id,
-                                   const Source& source,
-                                   BinaryOp op,
-                                   Expression* lhs,
-                                   Expression* rhs)
-    : Base(program_id, source), op_(op), lhs_(lhs), rhs_(rhs) {
-  TINT_ASSERT(AST, lhs_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs_, program_id);
-  TINT_ASSERT(AST, rhs_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, rhs_, program_id);
-  TINT_ASSERT(AST, op_ != BinaryOp::kNone);
+BinaryExpression::BinaryExpression(ProgramID pid,
+                                   const Source& src,
+                                   BinaryOp o,
+                                   Expression* l,
+                                   Expression* r)
+    : Base(pid, src), op(o), lhs(l), rhs(r) {
+  TINT_ASSERT(AST, lhs);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, lhs, program_id);
+  TINT_ASSERT(AST, rhs);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, rhs, program_id);
+  TINT_ASSERT(AST, op != BinaryOp::kNone);
 }
 
 BinaryExpression::BinaryExpression(BinaryExpression&&) = default;
@@ -40,10 +40,10 @@
 
 BinaryExpression* BinaryExpression::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* l = ctx->Clone(lhs_);
-  auto* r = ctx->Clone(rhs_);
-  return ctx->dst->create<BinaryExpression>(src, op_, l, r);
+  auto src = ctx->Clone(source);
+  auto* l = ctx->Clone(lhs);
+  auto* r = ctx->Clone(rhs);
+  return ctx->dst->create<BinaryExpression>(src, op, l, r);
 }
 
 }  // namespace ast
diff --git a/src/ast/binary_expression.h b/src/ast/binary_expression.h
index fedcd06..8c088f4 100644
--- a/src/ast/binary_expression.h
+++ b/src/ast/binary_expression.h
@@ -61,45 +61,42 @@
   BinaryExpression(BinaryExpression&&);
   ~BinaryExpression() override;
 
-  /// @returns the binary op type
-  BinaryOp op() const { return op_; }
-
   /// @returns true if the op is and
-  bool IsAnd() const { return op_ == BinaryOp::kAnd; }
+  bool IsAnd() const { return op == BinaryOp::kAnd; }
   /// @returns true if the op is or
-  bool IsOr() const { return op_ == BinaryOp::kOr; }
+  bool IsOr() const { return op == BinaryOp::kOr; }
   /// @returns true if the op is xor
-  bool IsXor() const { return op_ == BinaryOp::kXor; }
+  bool IsXor() const { return op == BinaryOp::kXor; }
   /// @returns true if the op is logical and
-  bool IsLogicalAnd() const { return op_ == BinaryOp::kLogicalAnd; }
+  bool IsLogicalAnd() const { return op == BinaryOp::kLogicalAnd; }
   /// @returns true if the op is logical or
-  bool IsLogicalOr() const { return op_ == BinaryOp::kLogicalOr; }
+  bool IsLogicalOr() const { return op == BinaryOp::kLogicalOr; }
   /// @returns true if the op is equal
-  bool IsEqual() const { return op_ == BinaryOp::kEqual; }
+  bool IsEqual() const { return op == BinaryOp::kEqual; }
   /// @returns true if the op is not equal
-  bool IsNotEqual() const { return op_ == BinaryOp::kNotEqual; }
+  bool IsNotEqual() const { return op == BinaryOp::kNotEqual; }
   /// @returns true if the op is less than
-  bool IsLessThan() const { return op_ == BinaryOp::kLessThan; }
+  bool IsLessThan() const { return op == BinaryOp::kLessThan; }
   /// @returns true if the op is greater than
-  bool IsGreaterThan() const { return op_ == BinaryOp::kGreaterThan; }
+  bool IsGreaterThan() const { return op == BinaryOp::kGreaterThan; }
   /// @returns true if the op is less than equal
-  bool IsLessThanEqual() const { return op_ == BinaryOp::kLessThanEqual; }
+  bool IsLessThanEqual() const { return op == BinaryOp::kLessThanEqual; }
   /// @returns true if the op is greater than equal
-  bool IsGreaterThanEqual() const { return op_ == BinaryOp::kGreaterThanEqual; }
+  bool IsGreaterThanEqual() const { return op == BinaryOp::kGreaterThanEqual; }
   /// @returns true if the op is shift left
-  bool IsShiftLeft() const { return op_ == BinaryOp::kShiftLeft; }
+  bool IsShiftLeft() const { return op == BinaryOp::kShiftLeft; }
   /// @returns true if the op is shift right
-  bool IsShiftRight() const { return op_ == BinaryOp::kShiftRight; }
+  bool IsShiftRight() const { return op == BinaryOp::kShiftRight; }
   /// @returns true if the op is add
-  bool IsAdd() const { return op_ == BinaryOp::kAdd; }
+  bool IsAdd() const { return op == BinaryOp::kAdd; }
   /// @returns true if the op is subtract
-  bool IsSubtract() const { return op_ == BinaryOp::kSubtract; }
+  bool IsSubtract() const { return op == BinaryOp::kSubtract; }
   /// @returns true if the op is multiply
-  bool IsMultiply() const { return op_ == BinaryOp::kMultiply; }
+  bool IsMultiply() const { return op == BinaryOp::kMultiply; }
   /// @returns true if the op is divide
-  bool IsDivide() const { return op_ == BinaryOp::kDivide; }
+  bool IsDivide() const { return op == BinaryOp::kDivide; }
   /// @returns true if the op is modulo
-  bool IsModulo() const { return op_ == BinaryOp::kModulo; }
+  bool IsModulo() const { return op == BinaryOp::kModulo; }
   /// @returns true if the op is an arithmetic operation
   bool IsArithmetic() const;
   /// @returns true if the op is a comparison operation
@@ -109,27 +106,25 @@
   /// @returns true if the op is a bit shift operation
   bool IsBitshift() const;
 
-  /// @returns the left side expression
-  Expression* lhs() const { return lhs_; }
-  /// @returns the right side expression
-  Expression* rhs() const { return rhs_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   BinaryExpression* Clone(CloneContext* ctx) const override;
 
+  /// the binary op type
+  BinaryOp const op;
+  /// the left side expression
+  Expression* const lhs;
+  /// the right side expression
+  Expression* const rhs;
+
  private:
   BinaryExpression(const BinaryExpression&) = delete;
-
-  BinaryOp const op_;
-  Expression* const lhs_;
-  Expression* const rhs_;
 };
 
 inline bool BinaryExpression::IsArithmetic() const {
-  switch (op_) {
+  switch (op) {
     case ast::BinaryOp::kAdd:
     case ast::BinaryOp::kSubtract:
     case ast::BinaryOp::kMultiply:
@@ -142,7 +137,7 @@
 }
 
 inline bool BinaryExpression::IsComparison() const {
-  switch (op_) {
+  switch (op) {
     case ast::BinaryOp::kEqual:
     case ast::BinaryOp::kNotEqual:
     case ast::BinaryOp::kLessThan:
@@ -156,7 +151,7 @@
 }
 
 inline bool BinaryExpression::IsBitwise() const {
-  switch (op_) {
+  switch (op) {
     case ast::BinaryOp::kAnd:
     case ast::BinaryOp::kOr:
     case ast::BinaryOp::kXor:
@@ -167,7 +162,7 @@
 }
 
 inline bool BinaryExpression::IsBitshift() const {
-  switch (op_) {
+  switch (op) {
     case ast::BinaryOp::kShiftLeft:
     case ast::BinaryOp::kShiftRight:
       return true;
diff --git a/src/ast/binary_expression_test.cc b/src/ast/binary_expression_test.cc
index 343e073..379385e 100644
--- a/src/ast/binary_expression_test.cc
+++ b/src/ast/binary_expression_test.cc
@@ -26,9 +26,9 @@
   auto* rhs = Expr("rhs");
 
   auto* r = create<BinaryExpression>(BinaryOp::kEqual, lhs, rhs);
-  EXPECT_EQ(r->lhs(), lhs);
-  EXPECT_EQ(r->rhs(), rhs);
-  EXPECT_EQ(r->op(), BinaryOp::kEqual);
+  EXPECT_EQ(r->lhs, lhs);
+  EXPECT_EQ(r->rhs, rhs);
+  EXPECT_EQ(r->op, BinaryOp::kEqual);
 }
 
 TEST_F(BinaryExpressionTest, Creation_WithSource) {
@@ -37,7 +37,7 @@
 
   auto* r = create<BinaryExpression>(Source{Source::Location{20, 2}},
                                      BinaryOp::kEqual, lhs, rhs);
-  auto src = r->source();
+  auto src = r->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/binding_decoration.cc b/src/ast/binding_decoration.cc
index 3dbce49..1cdc219 100644
--- a/src/ast/binding_decoration.cc
+++ b/src/ast/binding_decoration.cc
@@ -23,21 +23,21 @@
 namespace tint {
 namespace ast {
 
-BindingDecoration::BindingDecoration(ProgramID program_id,
-                                     const Source& source,
+BindingDecoration::BindingDecoration(ProgramID pid,
+                                     const Source& src,
                                      uint32_t val)
-    : Base(program_id, source), value_(val) {}
+    : Base(pid, src), value(val) {}
 
 BindingDecoration::~BindingDecoration() = default;
 
-std::string BindingDecoration::name() const {
+std::string BindingDecoration::Name() const {
   return "binding";
 }
 
 BindingDecoration* BindingDecoration::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<BindingDecoration>(src, value_);
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<BindingDecoration>(src, value);
 }
 
 }  // namespace ast
diff --git a/src/ast/binding_decoration.h b/src/ast/binding_decoration.h
index 0bb68a9..d9c2c14 100644
--- a/src/ast/binding_decoration.h
+++ b/src/ast/binding_decoration.h
@@ -26,17 +26,14 @@
 class BindingDecoration : public Castable<BindingDecoration, Decoration> {
  public:
   /// constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this decoration
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param value the binding value
-  BindingDecoration(ProgramID program_id, const Source& source, uint32_t value);
+  BindingDecoration(ProgramID pid, const Source& src, uint32_t value);
   ~BindingDecoration() override;
 
-  /// @returns the binding value
-  uint32_t value() const { return value_; }
-
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -44,8 +41,8 @@
   /// @return the newly cloned node
   BindingDecoration* Clone(CloneContext* ctx) const override;
 
- private:
-  uint32_t const value_;
+  /// the binding value
+  uint32_t const value;
 };
 
 }  // namespace ast
diff --git a/src/ast/binding_decoration_test.cc b/src/ast/binding_decoration_test.cc
index 7ebf189..92feb3a 100644
--- a/src/ast/binding_decoration_test.cc
+++ b/src/ast/binding_decoration_test.cc
@@ -23,7 +23,7 @@
 
 TEST_F(BindingDecorationTest, Creation) {
   auto* d = create<BindingDecoration>(2);
-  EXPECT_EQ(2u, d->value());
+  EXPECT_EQ(2u, d->value);
 }
 
 }  // namespace
diff --git a/src/ast/bitcast_expression.cc b/src/ast/bitcast_expression.cc
index 268a51f..e58b5e5 100644
--- a/src/ast/bitcast_expression.cc
+++ b/src/ast/bitcast_expression.cc
@@ -21,13 +21,13 @@
 namespace tint {
 namespace ast {
 
-BitcastExpression::BitcastExpression(ProgramID program_id,
-                                     const Source& source,
-                                     ast::Type* type,
-                                     Expression* expr)
-    : Base(program_id, source), type_(type), expr_(expr) {
-  TINT_ASSERT(AST, type_);
-  TINT_ASSERT(AST, expr_);
+BitcastExpression::BitcastExpression(ProgramID pid,
+                                     const Source& src,
+                                     ast::Type* t,
+                                     Expression* e)
+    : Base(pid, src), type(t), expr(e) {
+  TINT_ASSERT(AST, type);
+  TINT_ASSERT(AST, expr);
   TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, expr, program_id);
 }
 
@@ -36,10 +36,10 @@
 
 BitcastExpression* BitcastExpression::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* ty = ctx->Clone(type());
-  auto* e = ctx->Clone(expr_);
-  return ctx->dst->create<BitcastExpression>(src, ty, e);
+  auto src = ctx->Clone(source);
+  auto* t = ctx->Clone(type);
+  auto* e = ctx->Clone(expr);
+  return ctx->dst->create<BitcastExpression>(src, t, e);
 }
 
 }  // namespace ast
diff --git a/src/ast/bitcast_expression.h b/src/ast/bitcast_expression.h
index 413e64d..6a0a60a 100644
--- a/src/ast/bitcast_expression.h
+++ b/src/ast/bitcast_expression.h
@@ -39,22 +39,19 @@
   BitcastExpression(BitcastExpression&&);
   ~BitcastExpression() override;
 
-  /// @returns the left side expression
-  ast::Type* type() const { return type_; }
-  /// @returns the expression
-  Expression* expr() const { return expr_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   BitcastExpression* Clone(CloneContext* ctx) const override;
 
+  /// the target cast type
+  ast::Type* const type;
+  /// the expression
+  Expression* const expr;
+
  private:
   BitcastExpression(const BitcastExpression&) = delete;
-
-  ast::Type* const type_;
-  Expression* const expr_;
 };
 
 }  // namespace ast
diff --git a/src/ast/bitcast_expression_test.cc b/src/ast/bitcast_expression_test.cc
index 3af6a75..df0015f 100644
--- a/src/ast/bitcast_expression_test.cc
+++ b/src/ast/bitcast_expression_test.cc
@@ -27,8 +27,8 @@
   auto* expr = Expr("expr");
 
   auto* exp = create<BitcastExpression>(ty.f32(), expr);
-  EXPECT_TRUE(exp->type()->Is<ast::F32>());
-  ASSERT_EQ(exp->expr(), expr);
+  EXPECT_TRUE(exp->type->Is<ast::F32>());
+  ASSERT_EQ(exp->expr, expr);
 }
 
 TEST_F(BitcastExpressionTest, CreateWithSource) {
@@ -36,7 +36,7 @@
 
   auto* exp = create<BitcastExpression>(Source{Source::Location{20, 2}},
                                         ty.f32(), expr);
-  auto src = exp->source();
+  auto src = exp->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/block_statement.cc b/src/ast/block_statement.cc
index 01190f4..b0642f4 100644
--- a/src/ast/block_statement.cc
+++ b/src/ast/block_statement.cc
@@ -21,11 +21,11 @@
 namespace tint {
 namespace ast {
 
-BlockStatement::BlockStatement(ProgramID program_id,
-                               const Source& source,
-                               const StatementList& statements)
-    : Base(program_id, source), statements_(std::move(statements)) {
-  for (auto* stmt : *this) {
+BlockStatement::BlockStatement(ProgramID pid,
+                               const Source& src,
+                               const StatementList& stmts)
+    : Base(pid, src), statements(std::move(stmts)) {
+  for (auto* stmt : statements) {
     TINT_ASSERT(AST, stmt);
     TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, stmt, program_id);
   }
@@ -37,8 +37,8 @@
 
 BlockStatement* BlockStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto stmts = ctx->Clone(statements_);
+  auto src = ctx->Clone(source);
+  auto stmts = ctx->Clone(statements);
   return ctx->dst->create<BlockStatement>(src, stmts);
 }
 
diff --git a/src/ast/block_statement.h b/src/ast/block_statement.h
index dad2858..f37db9e 100644
--- a/src/ast/block_statement.h
+++ b/src/ast/block_statement.h
@@ -36,40 +36,13 @@
   BlockStatement(BlockStatement&&);
   ~BlockStatement() override;
 
-  /// @returns the StatementList
-  const StatementList& list() const { return statements_; }
-
-  /// @returns true if the block is empty
-  bool empty() const { return statements_.empty(); }
-  /// @returns the number of statements directly in the block
-  size_t size() const { return statements_.size(); }
+  /// @returns true if the block has no statements
+  bool Empty() const { return statements.empty(); }
 
   /// @returns the last statement in the block or nullptr if block empty
-  const Statement* last() const {
-    return statements_.empty() ? nullptr : statements_.back();
+  Statement* Last() const {
+    return statements.empty() ? nullptr : statements.back();
   }
-  /// @returns the last statement in the block or nullptr if block empty
-  Statement* last() {
-    return statements_.empty() ? nullptr : statements_.back();
-  }
-
-  /// Retrieves the statement at `idx`
-  /// @param idx the index. The index is not bounds checked.
-  /// @returns the statement at `idx`
-  Statement* get(size_t idx) const { return statements_[idx]; }
-
-  /// Retrieves the statement at `idx`
-  /// @param idx the index. The index is not bounds checked.
-  /// @returns the statement at `idx`
-  Statement* operator[](size_t idx) const { return statements_[idx]; }
-
-  /// @returns the beginning iterator
-  StatementList::const_iterator begin() const { return statements_.begin(); }
-  /// @returns the ending iterator
-  StatementList::const_iterator end() const { return statements_.end(); }
-
-  /// @returns the statement list
-  const StatementList& statements() const { return statements_; }
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -77,10 +50,11 @@
   /// @return the newly cloned node
   BlockStatement* Clone(CloneContext* ctx) const override;
 
+  /// the statement list
+  StatementList const statements;
+
  private:
   BlockStatement(const BlockStatement&) = delete;
-
-  StatementList const statements_;
 };
 
 }  // namespace ast
diff --git a/src/ast/block_statement_test.cc b/src/ast/block_statement_test.cc
index 031523a..70f44d5 100644
--- a/src/ast/block_statement_test.cc
+++ b/src/ast/block_statement_test.cc
@@ -29,14 +29,14 @@
 
   auto* b = create<BlockStatement>(StatementList{d});
 
-  ASSERT_EQ(b->size(), 1u);
-  EXPECT_EQ((*b)[0], ptr);
+  ASSERT_EQ(b->statements.size(), 1u);
+  EXPECT_EQ(b->statements[0], ptr);
 }
 
 TEST_F(BlockStatementTest, Creation_WithSource) {
   auto* b = create<BlockStatement>(Source{Source::Location{20, 2}},
                                    ast::StatementList{});
-  auto src = b->source();
+  auto src = b->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/bool.cc b/src/ast/bool.cc
index 5ca1cdb..f7caf9b 100644
--- a/src/ast/bool.cc
+++ b/src/ast/bool.cc
@@ -21,8 +21,7 @@
 namespace tint {
 namespace ast {
 
-Bool::Bool(ProgramID program_id, const Source& source)
-    : Base(program_id, source) {}
+Bool::Bool(ProgramID pid, const Source& src) : Base(pid, src) {}
 
 Bool::Bool(Bool&&) = default;
 
@@ -33,7 +32,7 @@
 }
 
 Bool* Bool::Clone(CloneContext* ctx) const {
-  auto src = ctx->Clone(source());
+  auto src = ctx->Clone(source);
   return ctx->dst->create<Bool>(src);
 }
 
diff --git a/src/ast/bool.h b/src/ast/bool.h
index 8031319..d3d8702 100644
--- a/src/ast/bool.h
+++ b/src/ast/bool.h
@@ -32,9 +32,9 @@
 class Bool : public Castable<Bool, Type> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
-  Bool(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  Bool(ProgramID pid, const Source& src);
   /// Move constructor
   Bool(Bool&&);
   ~Bool() override;
diff --git a/src/ast/bool_literal.cc b/src/ast/bool_literal.cc
index 5c7554a..e6f256e 100644
--- a/src/ast/bool_literal.cc
+++ b/src/ast/bool_literal.cc
@@ -21,19 +21,15 @@
 namespace tint {
 namespace ast {
 
-BoolLiteral::BoolLiteral(ProgramID program_id, const Source& source, bool value)
-    : Base(program_id, source), value_(value) {}
+BoolLiteral::BoolLiteral(ProgramID pid, const Source& src, bool val)
+    : Base(pid, src), value(val) {}
 
 BoolLiteral::~BoolLiteral() = default;
 
-std::string BoolLiteral::name() const {
-  return value_ ? "__bool_true" : "__bool_false";
-}
-
 BoolLiteral* BoolLiteral::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<BoolLiteral>(src, value_);
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<BoolLiteral>(src, value);
 }
 
 }  // namespace ast
diff --git a/src/ast/bool_literal.h b/src/ast/bool_literal.h
index b728276..da5f571 100644
--- a/src/ast/bool_literal.h
+++ b/src/ast/bool_literal.h
@@ -26,19 +26,12 @@
 class BoolLiteral : public Castable<BoolLiteral, Literal> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the input source
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param value the bool literals value
-  BoolLiteral(ProgramID program_id, const Source& source, bool value);
+  BoolLiteral(ProgramID pid, const Source& src, bool value);
   ~BoolLiteral() override;
 
-  /// @returns true if the bool literal is true
-  bool IsTrue() const { return value_; }
-  /// @returns true if the bool literal is false
-  bool IsFalse() const { return !value_; }
-
-  /// @returns the name for this literal. This name is unique to this value.
-  std::string name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -46,8 +39,8 @@
   /// @return the newly cloned node
   BoolLiteral* Clone(CloneContext* ctx) const override;
 
- private:
-  bool const value_;
+  /// The boolean literal value
+  bool const value;
 };
 
 }  // namespace ast
diff --git a/src/ast/bool_literal_test.cc b/src/ast/bool_literal_test.cc
index d36671a..67d306e 100644
--- a/src/ast/bool_literal_test.cc
+++ b/src/ast/bool_literal_test.cc
@@ -23,15 +23,13 @@
 TEST_F(BoolLiteralTest, True) {
   auto* b = create<BoolLiteral>(true);
   ASSERT_TRUE(b->Is<BoolLiteral>());
-  ASSERT_TRUE(b->IsTrue());
-  ASSERT_FALSE(b->IsFalse());
+  ASSERT_TRUE(b->value);
 }
 
 TEST_F(BoolLiteralTest, False) {
   auto* b = create<BoolLiteral>(false);
   ASSERT_TRUE(b->Is<BoolLiteral>());
-  ASSERT_FALSE(b->IsTrue());
-  ASSERT_TRUE(b->IsFalse());
+  ASSERT_FALSE(b->value);
 }
 
 }  // namespace
diff --git a/src/ast/break_statement.cc b/src/ast/break_statement.cc
index 154bc32..8bdde65 100644
--- a/src/ast/break_statement.cc
+++ b/src/ast/break_statement.cc
@@ -21,8 +21,8 @@
 namespace tint {
 namespace ast {
 
-BreakStatement::BreakStatement(ProgramID program_id, const Source& source)
-    : Base(program_id, source) {}
+BreakStatement::BreakStatement(ProgramID pid, const Source& src)
+    : Base(pid, src) {}
 
 BreakStatement::BreakStatement(BreakStatement&&) = default;
 
@@ -30,7 +30,7 @@
 
 BreakStatement* BreakStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
+  auto src = ctx->Clone(source);
   return ctx->dst->create<BreakStatement>(src);
 }
 
diff --git a/src/ast/break_statement.h b/src/ast/break_statement.h
index 67a20d0..2bc74f9 100644
--- a/src/ast/break_statement.h
+++ b/src/ast/break_statement.h
@@ -24,9 +24,9 @@
 class BreakStatement : public Castable<BreakStatement, Statement> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the break statement source
-  BreakStatement(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  BreakStatement(ProgramID pid, const Source& src);
   /// Move constructor
   BreakStatement(BreakStatement&&);
   ~BreakStatement() override;
diff --git a/src/ast/break_statement_test.cc b/src/ast/break_statement_test.cc
index 10d8e8e..ed56b7b 100644
--- a/src/ast/break_statement_test.cc
+++ b/src/ast/break_statement_test.cc
@@ -24,7 +24,7 @@
 
 TEST_F(BreakStatementTest, Creation_WithSource) {
   auto* stmt = create<BreakStatement>(Source{Source::Location{20, 2}});
-  auto src = stmt->source();
+  auto src = stmt->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/builtin_decoration.cc b/src/ast/builtin_decoration.cc
index c891493..db3dfe4 100644
--- a/src/ast/builtin_decoration.cc
+++ b/src/ast/builtin_decoration.cc
@@ -23,21 +23,21 @@
 namespace tint {
 namespace ast {
 
-BuiltinDecoration::BuiltinDecoration(ProgramID program_id,
-                                     const Source& source,
-                                     Builtin builtin)
-    : Base(program_id, source), builtin_(builtin) {}
+BuiltinDecoration::BuiltinDecoration(ProgramID pid,
+                                     const Source& src,
+                                     Builtin b)
+    : Base(pid, src), builtin(b) {}
 
 BuiltinDecoration::~BuiltinDecoration() = default;
 
-std::string BuiltinDecoration::name() const {
+std::string BuiltinDecoration::Name() const {
   return "builtin";
 }
 
 BuiltinDecoration* BuiltinDecoration::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<BuiltinDecoration>(src, builtin_);
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<BuiltinDecoration>(src, builtin);
 }
 
 }  // namespace ast
diff --git a/src/ast/builtin_decoration.h b/src/ast/builtin_decoration.h
index cfb201c..d312103 100644
--- a/src/ast/builtin_decoration.h
+++ b/src/ast/builtin_decoration.h
@@ -27,19 +27,14 @@
 class BuiltinDecoration : public Castable<BuiltinDecoration, Decoration> {
  public:
   /// constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this decoration
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param builtin the builtin value
-  BuiltinDecoration(ProgramID program_id,
-                    const Source& source,
-                    Builtin builtin);
+  BuiltinDecoration(ProgramID pid, const Source& src, Builtin builtin);
   ~BuiltinDecoration() override;
 
-  /// @returns the builtin value
-  Builtin value() const { return builtin_; }
-
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -47,8 +42,8 @@
   /// @return the newly cloned node
   BuiltinDecoration* Clone(CloneContext* ctx) const override;
 
- private:
-  Builtin const builtin_;
+  /// The builtin value
+  Builtin const builtin;
 };
 
 }  // namespace ast
diff --git a/src/ast/builtin_decoration_test.cc b/src/ast/builtin_decoration_test.cc
index e42999d..4efafae 100644
--- a/src/ast/builtin_decoration_test.cc
+++ b/src/ast/builtin_decoration_test.cc
@@ -23,7 +23,7 @@
 
 TEST_F(BuiltinDecorationTest, Creation) {
   auto* d = create<BuiltinDecoration>(Builtin::kFragDepth);
-  EXPECT_EQ(Builtin::kFragDepth, d->value());
+  EXPECT_EQ(Builtin::kFragDepth, d->builtin);
 }
 
 }  // namespace
diff --git a/src/ast/call_expression.cc b/src/ast/call_expression.cc
index 7cd0f2a..43e7a44 100644
--- a/src/ast/call_expression.cc
+++ b/src/ast/call_expression.cc
@@ -21,14 +21,14 @@
 namespace tint {
 namespace ast {
 
-CallExpression::CallExpression(ProgramID program_id,
-                               const Source& source,
-                               IdentifierExpression* func,
-                               ExpressionList args)
-    : Base(program_id, source), func_(func), args_(args) {
-  TINT_ASSERT(AST, func_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func_, program_id);
-  for (auto* arg : args_) {
+CallExpression::CallExpression(ProgramID pid,
+                               const Source& src,
+                               IdentifierExpression* fn,
+                               ExpressionList a)
+    : Base(pid, src), func(fn), args(a) {
+  TINT_ASSERT(AST, func);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id);
+  for (auto* arg : args) {
     TINT_ASSERT(AST, arg);
     TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, arg, program_id);
   }
@@ -40,9 +40,9 @@
 
 CallExpression* CallExpression::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* fn = ctx->Clone(func_);
-  auto p = ctx->Clone(args_);
+  auto src = ctx->Clone(source);
+  auto* fn = ctx->Clone(func);
+  auto p = ctx->Clone(args);
   return ctx->dst->create<CallExpression>(src, fn, p);
 }
 
diff --git a/src/ast/call_expression.h b/src/ast/call_expression.h
index fef115a..7cf625e 100644
--- a/src/ast/call_expression.h
+++ b/src/ast/call_expression.h
@@ -39,22 +39,19 @@
   CallExpression(CallExpression&&);
   ~CallExpression() override;
 
-  /// @returns the func
-  IdentifierExpression* func() const { return func_; }
-  /// @returns the arguments
-  const ExpressionList& args() const { return args_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   CallExpression* Clone(CloneContext* ctx) const override;
 
+  /// The target function
+  IdentifierExpression* const func;
+  /// The arguments
+  ExpressionList const args;
+
  private:
   CallExpression(const CallExpression&) = delete;
-
-  IdentifierExpression* const func_;
-  ExpressionList const args_;
 };
 
 }  // namespace ast
diff --git a/src/ast/call_expression_test.cc b/src/ast/call_expression_test.cc
index b36c39a..af250c0 100644
--- a/src/ast/call_expression_test.cc
+++ b/src/ast/call_expression_test.cc
@@ -28,9 +28,9 @@
   params.push_back(Expr("param2"));
 
   auto* stmt = create<CallExpression>(func, params);
-  EXPECT_EQ(stmt->func(), func);
+  EXPECT_EQ(stmt->func, func);
 
-  const auto& vec = stmt->args();
+  const auto& vec = stmt->args;
   ASSERT_EQ(vec.size(), 2u);
   EXPECT_EQ(vec[0], params[0]);
   EXPECT_EQ(vec[1], params[1]);
@@ -40,7 +40,7 @@
   auto* func = Expr("func");
   auto* stmt = create<CallExpression>(Source{Source::Location{20, 2}}, func,
                                       ExpressionList{});
-  auto src = stmt->source();
+  auto src = stmt->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/call_statement.cc b/src/ast/call_statement.cc
index c0ac3ad..540f2ad 100644
--- a/src/ast/call_statement.cc
+++ b/src/ast/call_statement.cc
@@ -21,12 +21,12 @@
 namespace tint {
 namespace ast {
 
-CallStatement::CallStatement(ProgramID program_id,
-                             const Source& source,
+CallStatement::CallStatement(ProgramID pid,
+                             const Source& src,
                              CallExpression* call)
-    : Base(program_id, source), call_(call) {
-  TINT_ASSERT(AST, call_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, call_, program_id);
+    : Base(pid, src), expr(call) {
+  TINT_ASSERT(AST, expr);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, expr, program_id);
 }
 
 CallStatement::CallStatement(CallStatement&&) = default;
@@ -35,8 +35,8 @@
 
 CallStatement* CallStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* call = ctx->Clone(call_);
+  auto src = ctx->Clone(source);
+  auto* call = ctx->Clone(expr);
   return ctx->dst->create<CallStatement>(src, call);
 }
 
diff --git a/src/ast/call_statement.h b/src/ast/call_statement.h
index e389503..2eb5aa3 100644
--- a/src/ast/call_statement.h
+++ b/src/ast/call_statement.h
@@ -25,29 +25,25 @@
 class CallStatement : public Castable<CallStatement, Statement> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the input source for the statement
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node for the statement
   /// @param call the function
-  CallStatement(ProgramID program_id,
-                const Source& source,
-                CallExpression* call);
+  CallStatement(ProgramID pid, const Source& src, CallExpression* call);
   /// Move constructor
   CallStatement(CallStatement&&);
   ~CallStatement() override;
 
-  /// @returns the call expression
-  CallExpression* expr() const { return call_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   CallStatement* Clone(CloneContext* ctx) const override;
 
+  /// The call expression
+  CallExpression* const expr;
+
  private:
   CallStatement(const CallStatement&) = delete;
-
-  CallExpression* const call_;
 };
 
 }  // namespace ast
diff --git a/src/ast/call_statement_test.cc b/src/ast/call_statement_test.cc
index 3bff4cf..b5bd7e9 100644
--- a/src/ast/call_statement_test.cc
+++ b/src/ast/call_statement_test.cc
@@ -27,7 +27,7 @@
   auto* expr = create<CallExpression>(Expr("func"), ExpressionList{});
 
   auto* c = create<CallStatement>(expr);
-  EXPECT_EQ(c->expr(), expr);
+  EXPECT_EQ(c->expr, expr);
 }
 
 TEST_F(CallStatementTest, IsCall) {
diff --git a/src/ast/case_statement.cc b/src/ast/case_statement.cc
index 82406df..71fe7f9 100644
--- a/src/ast/case_statement.cc
+++ b/src/ast/case_statement.cc
@@ -21,13 +21,13 @@
 namespace tint {
 namespace ast {
 
-CaseStatement::CaseStatement(ProgramID program_id,
-                             const Source& source,
-                             CaseSelectorList selectors,
-                             BlockStatement* body)
-    : Base(program_id, source), selectors_(selectors), body_(body) {
-  TINT_ASSERT(AST, body_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body_, program_id);
+CaseStatement::CaseStatement(ProgramID pid,
+                             const Source& src,
+                             CaseSelectorList s,
+                             BlockStatement* b)
+    : Base(pid, src), selectors(s), body(b) {
+  TINT_ASSERT(AST, body);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
   for (auto* selector : selectors) {
     TINT_ASSERT(AST, selector);
     TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, selector, program_id);
@@ -40,9 +40,9 @@
 
 CaseStatement* CaseStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto sel = ctx->Clone(selectors_);
-  auto* b = ctx->Clone(body_);
+  auto src = ctx->Clone(source);
+  auto sel = ctx->Clone(selectors);
+  auto* b = ctx->Clone(body);
   return ctx->dst->create<CaseStatement>(src, sel, b);
 }
 
diff --git a/src/ast/case_statement.h b/src/ast/case_statement.h
index ebf3e9a..eb74d59 100644
--- a/src/ast/case_statement.h
+++ b/src/ast/case_statement.h
@@ -30,27 +30,20 @@
 class CaseStatement : public Castable<CaseStatement, Statement> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source information
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param selectors the case selectors
   /// @param body the case body
-  CaseStatement(ProgramID program_id,
-                const Source& source,
+  CaseStatement(ProgramID pid,
+                const Source& src,
                 CaseSelectorList selectors,
                 BlockStatement* body);
   /// Move constructor
   CaseStatement(CaseStatement&&);
   ~CaseStatement() override;
 
-  /// @returns the case selectors, empty if none set
-  const CaseSelectorList& selectors() const { return selectors_; }
   /// @returns true if this is a default statement
-  bool IsDefault() const { return selectors_.empty(); }
-
-  /// @returns the case body
-  const BlockStatement* body() const { return body_; }
-  /// @returns the case body
-  BlockStatement* body() { return body_; }
+  bool IsDefault() const { return selectors.empty(); }
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -58,11 +51,14 @@
   /// @return the newly cloned node
   CaseStatement* Clone(CloneContext* ctx) const override;
 
+  /// The case selectors, empty if none set
+  CaseSelectorList const selectors;
+
+  /// The case body
+  BlockStatement* const body;
+
  private:
   CaseStatement(const CaseStatement&) = delete;
-
-  CaseSelectorList const selectors_;
-  BlockStatement* const body_;
 };
 
 /// A list of case statements
diff --git a/src/ast/case_statement_test.cc b/src/ast/case_statement_test.cc
index aeb9097..7fc92ec 100644
--- a/src/ast/case_statement_test.cc
+++ b/src/ast/case_statement_test.cc
@@ -34,10 +34,10 @@
   auto* body = create<BlockStatement>(StatementList{discard});
 
   auto* c = create<CaseStatement>(b, body);
-  ASSERT_EQ(c->selectors().size(), 1u);
-  EXPECT_EQ(c->selectors()[0], selector);
-  ASSERT_EQ(c->body()->size(), 1u);
-  EXPECT_EQ(c->body()->get(0), discard);
+  ASSERT_EQ(c->selectors.size(), 1u);
+  EXPECT_EQ(c->selectors[0], selector);
+  ASSERT_EQ(c->body->statements.size(), 1u);
+  EXPECT_EQ(c->body->statements[0], discard);
 }
 
 TEST_F(CaseStatementTest, Creation_u32) {
@@ -49,10 +49,10 @@
   auto* body = create<BlockStatement>(StatementList{discard});
 
   auto* c = create<CaseStatement>(b, body);
-  ASSERT_EQ(c->selectors().size(), 1u);
-  EXPECT_EQ(c->selectors()[0], selector);
-  ASSERT_EQ(c->body()->size(), 1u);
-  EXPECT_EQ(c->body()->get(0), discard);
+  ASSERT_EQ(c->selectors.size(), 1u);
+  EXPECT_EQ(c->selectors[0], selector);
+  ASSERT_EQ(c->body->statements.size(), 1u);
+  EXPECT_EQ(c->body->statements[0], discard);
 }
 
 TEST_F(CaseStatementTest, Creation_WithSource) {
@@ -63,7 +63,7 @@
       create<DiscardStatement>(),
   });
   auto* c = create<CaseStatement>(Source{Source::Location{20, 2}}, b, body);
-  auto src = c->source();
+  auto src = c->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/constructor_expression.cc b/src/ast/constructor_expression.cc
index c8d4ea2..e1a8224 100644
--- a/src/ast/constructor_expression.cc
+++ b/src/ast/constructor_expression.cc
@@ -23,9 +23,8 @@
 
 ConstructorExpression::ConstructorExpression(ConstructorExpression&&) = default;
 
-ConstructorExpression::ConstructorExpression(ProgramID program_id,
-                                             const Source& source)
-    : Base(program_id, source) {}
+ConstructorExpression::ConstructorExpression(ProgramID pid, const Source& src)
+    : Base(pid, src) {}
 
 }  // namespace ast
 }  // namespace tint
diff --git a/src/ast/constructor_expression.h b/src/ast/constructor_expression.h
index ce761ba..93a19fd 100644
--- a/src/ast/constructor_expression.h
+++ b/src/ast/constructor_expression.h
@@ -28,9 +28,9 @@
 
  protected:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the constructor source
-  ConstructorExpression(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  ConstructorExpression(ProgramID pid, const Source& src);
   /// Move constructor
   ConstructorExpression(ConstructorExpression&&);
 
diff --git a/src/ast/continue_statement.cc b/src/ast/continue_statement.cc
index a07572f..222f7f5 100644
--- a/src/ast/continue_statement.cc
+++ b/src/ast/continue_statement.cc
@@ -21,8 +21,8 @@
 namespace tint {
 namespace ast {
 
-ContinueStatement::ContinueStatement(ProgramID program_id, const Source& source)
-    : Base(program_id, source) {}
+ContinueStatement::ContinueStatement(ProgramID pid, const Source& src)
+    : Base(pid, src) {}
 
 ContinueStatement::ContinueStatement(ContinueStatement&&) = default;
 
@@ -30,7 +30,7 @@
 
 ContinueStatement* ContinueStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
+  auto src = ctx->Clone(source);
   return ctx->dst->create<ContinueStatement>(src);
 }
 
diff --git a/src/ast/continue_statement.h b/src/ast/continue_statement.h
index a618637..eaf799d 100644
--- a/src/ast/continue_statement.h
+++ b/src/ast/continue_statement.h
@@ -24,9 +24,9 @@
 class ContinueStatement : public Castable<ContinueStatement, Statement> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the continue statement source
-  ContinueStatement(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  ContinueStatement(ProgramID pid, const Source& src);
   /// Move constructor
   ContinueStatement(ContinueStatement&&);
   ~ContinueStatement() override;
diff --git a/src/ast/continue_statement_test.cc b/src/ast/continue_statement_test.cc
index addad15..1d3b490 100644
--- a/src/ast/continue_statement_test.cc
+++ b/src/ast/continue_statement_test.cc
@@ -24,7 +24,7 @@
 
 TEST_F(ContinueStatementTest, Creation_WithSource) {
   auto* stmt = create<ContinueStatement>(Source{Source::Location{20, 2}});
-  auto src = stmt->source();
+  auto src = stmt->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/decoration.h b/src/ast/decoration.h
index 0b2912e..d915de3 100644
--- a/src/ast/decoration.h
+++ b/src/ast/decoration.h
@@ -29,14 +29,13 @@
   ~Decoration() override;
 
   /// @returns the WGSL name for the decoration
-  virtual std::string name() const = 0;
+  virtual std::string Name() const = 0;
 
  protected:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this decoration
-  Decoration(ProgramID program_id, const Source& source)
-      : Base(program_id, source) {}
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  Decoration(ProgramID pid, const Source& src) : Base(pid, src) {}
 };
 
 /// A list of decorations
diff --git a/src/ast/depth_multisampled_texture.cc b/src/ast/depth_multisampled_texture.cc
index b822195..5985fee 100644
--- a/src/ast/depth_multisampled_texture.cc
+++ b/src/ast/depth_multisampled_texture.cc
@@ -28,10 +28,10 @@
 
 }  // namespace
 
-DepthMultisampledTexture::DepthMultisampledTexture(ProgramID program_id,
-                                                   const Source& source,
-                                                   TextureDimension dim)
-    : Base(program_id, source, dim) {
+DepthMultisampledTexture::DepthMultisampledTexture(ProgramID pid,
+                                                   const Source& src,
+                                                   TextureDimension d)
+    : Base(pid, src, d) {
   TINT_ASSERT(AST, IsValidDepthDimension(dim));
 }
 
@@ -42,14 +42,14 @@
 
 std::string DepthMultisampledTexture::FriendlyName(const SymbolTable&) const {
   std::ostringstream out;
-  out << "texture_depth_multisampled_" << dim();
+  out << "texture_depth_multisampled_" << dim;
   return out.str();
 }
 
 DepthMultisampledTexture* DepthMultisampledTexture::Clone(
     CloneContext* ctx) const {
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<DepthMultisampledTexture>(src, dim());
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<DepthMultisampledTexture>(src, dim);
 }
 
 }  // namespace ast
diff --git a/src/ast/depth_multisampled_texture.h b/src/ast/depth_multisampled_texture.h
index 4f23933..c274d93 100644
--- a/src/ast/depth_multisampled_texture.h
+++ b/src/ast/depth_multisampled_texture.h
@@ -27,11 +27,11 @@
     : public Castable<DepthMultisampledTexture, Texture> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param dim the dimensionality of the texture
-  DepthMultisampledTexture(ProgramID program_id,
-                           const Source& source,
+  DepthMultisampledTexture(ProgramID pid,
+                           const Source& src,
                            TextureDimension dim);
   /// Move constructor
   DepthMultisampledTexture(DepthMultisampledTexture&&);
diff --git a/src/ast/depth_multisampled_texture_test.cc b/src/ast/depth_multisampled_texture_test.cc
index 7c1ce0f..b75d2a6 100644
--- a/src/ast/depth_multisampled_texture_test.cc
+++ b/src/ast/depth_multisampled_texture_test.cc
@@ -24,7 +24,7 @@
 
 TEST_F(AstDepthMultisampledTextureTest, Dim) {
   auto* d = create<DepthMultisampledTexture>(TextureDimension::k2d);
-  EXPECT_EQ(d->dim(), TextureDimension::k2d);
+  EXPECT_EQ(d->dim, TextureDimension::k2d);
 }
 
 TEST_F(AstDepthMultisampledTextureTest, FriendlyName) {
diff --git a/src/ast/depth_texture.cc b/src/ast/depth_texture.cc
index 8cad4ba..39f576c 100644
--- a/src/ast/depth_texture.cc
+++ b/src/ast/depth_texture.cc
@@ -29,10 +29,8 @@
 
 }  // namespace
 
-DepthTexture::DepthTexture(ProgramID program_id,
-                           const Source& source,
-                           TextureDimension dim)
-    : Base(program_id, source, dim) {
+DepthTexture::DepthTexture(ProgramID pid, const Source& src, TextureDimension d)
+    : Base(pid, src, d) {
   TINT_ASSERT(AST, IsValidDepthDimension(dim));
 }
 
@@ -42,13 +40,13 @@
 
 std::string DepthTexture::FriendlyName(const SymbolTable&) const {
   std::ostringstream out;
-  out << "texture_depth_" << dim();
+  out << "texture_depth_" << dim;
   return out.str();
 }
 
 DepthTexture* DepthTexture::Clone(CloneContext* ctx) const {
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<DepthTexture>(src, dim());
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<DepthTexture>(src, dim);
 }
 
 }  // namespace ast
diff --git a/src/ast/depth_texture.h b/src/ast/depth_texture.h
index e0ff248..f2e1e10 100644
--- a/src/ast/depth_texture.h
+++ b/src/ast/depth_texture.h
@@ -26,12 +26,10 @@
 class DepthTexture : public Castable<DepthTexture, Texture> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param dim the dimensionality of the texture
-  DepthTexture(ProgramID program_id,
-               const Source& source,
-               TextureDimension dim);
+  DepthTexture(ProgramID pid, const Source& src, TextureDimension dim);
   /// Move constructor
   DepthTexture(DepthTexture&&);
   ~DepthTexture() override;
diff --git a/src/ast/depth_texture_test.cc b/src/ast/depth_texture_test.cc
index 9e760d9..2a0ec2b 100644
--- a/src/ast/depth_texture_test.cc
+++ b/src/ast/depth_texture_test.cc
@@ -31,7 +31,7 @@
 
 TEST_F(AstDepthTextureTest, Dim) {
   auto* d = create<DepthTexture>(TextureDimension::kCube);
-  EXPECT_EQ(d->dim(), TextureDimension::kCube);
+  EXPECT_EQ(d->dim, TextureDimension::kCube);
 }
 
 TEST_F(AstDepthTextureTest, FriendlyName) {
diff --git a/src/ast/disable_validation_decoration.cc b/src/ast/disable_validation_decoration.cc
index 8708cec..69c4605 100644
--- a/src/ast/disable_validation_decoration.cc
+++ b/src/ast/disable_validation_decoration.cc
@@ -21,15 +21,14 @@
 namespace tint {
 namespace ast {
 
-DisableValidationDecoration::DisableValidationDecoration(
-    ProgramID program_id,
-    DisabledValidation validation)
-    : Base(program_id), validation_(validation) {}
+DisableValidationDecoration::DisableValidationDecoration(ProgramID pid,
+                                                         DisabledValidation val)
+    : Base(pid), validation(val) {}
 
 DisableValidationDecoration::~DisableValidationDecoration() = default;
 
 std::string DisableValidationDecoration::InternalName() const {
-  switch (validation_) {
+  switch (validation) {
     case DisabledValidation::kFunctionHasNoBody:
       return "disable_validation__function_has_no_body";
     case DisabledValidation::kBindingPointCollision:
@@ -51,7 +50,7 @@
 DisableValidationDecoration* DisableValidationDecoration::Clone(
     CloneContext* ctx) const {
   return ctx->dst->ASTNodes().Create<DisableValidationDecoration>(
-      ctx->dst->ID(), validation_);
+      ctx->dst->ID(), validation);
 }
 
 }  // namespace ast
diff --git a/src/ast/disable_validation_decoration.h b/src/ast/disable_validation_decoration.h
index 5e8213f..2d0fd89 100644
--- a/src/ast/disable_validation_decoration.h
+++ b/src/ast/disable_validation_decoration.h
@@ -64,9 +64,6 @@
   /// Destructor
   ~DisableValidationDecoration() override;
 
-  /// @return the validation that this decoration disables
-  DisabledValidation Validation() const { return validation_; }
-
   /// @return a short description of the internal decoration which will be
   /// displayed in WGSL as `[[internal(<name>)]]` (but is not parsable).
   std::string InternalName() const override;
@@ -76,8 +73,8 @@
   /// @return the newly cloned object
   DisableValidationDecoration* Clone(CloneContext* ctx) const override;
 
- private:
-  DisabledValidation const validation_;
+  /// The validation that this decoration disables
+  DisabledValidation const validation;
 };
 
 }  // namespace ast
diff --git a/src/ast/discard_statement.cc b/src/ast/discard_statement.cc
index 129cc56..fbc5d28 100644
--- a/src/ast/discard_statement.cc
+++ b/src/ast/discard_statement.cc
@@ -21,8 +21,8 @@
 namespace tint {
 namespace ast {
 
-DiscardStatement::DiscardStatement(ProgramID program_id, const Source& source)
-    : Base(program_id, source) {}
+DiscardStatement::DiscardStatement(ProgramID pid, const Source& src)
+    : Base(pid, src) {}
 
 DiscardStatement::DiscardStatement(DiscardStatement&&) = default;
 
@@ -30,7 +30,7 @@
 
 DiscardStatement* DiscardStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
+  auto src = ctx->Clone(source);
   return ctx->dst->create<DiscardStatement>(src);
 }
 
diff --git a/src/ast/discard_statement.h b/src/ast/discard_statement.h
index 0a363c8..2159323 100644
--- a/src/ast/discard_statement.h
+++ b/src/ast/discard_statement.h
@@ -24,9 +24,9 @@
 class DiscardStatement : public Castable<DiscardStatement, Statement> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the discard statement source
-  DiscardStatement(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  DiscardStatement(ProgramID pid, const Source& src);
   /// Move constructor
   DiscardStatement(DiscardStatement&&);
   ~DiscardStatement() override;
diff --git a/src/ast/discard_statement_test.cc b/src/ast/discard_statement_test.cc
index 97b459e..b83e69b 100644
--- a/src/ast/discard_statement_test.cc
+++ b/src/ast/discard_statement_test.cc
@@ -24,19 +24,19 @@
 
 TEST_F(DiscardStatementTest, Creation) {
   auto* stmt = create<DiscardStatement>();
-  EXPECT_EQ(stmt->source().range.begin.line, 0u);
-  EXPECT_EQ(stmt->source().range.begin.column, 0u);
-  EXPECT_EQ(stmt->source().range.end.line, 0u);
-  EXPECT_EQ(stmt->source().range.end.column, 0u);
+  EXPECT_EQ(stmt->source.range.begin.line, 0u);
+  EXPECT_EQ(stmt->source.range.begin.column, 0u);
+  EXPECT_EQ(stmt->source.range.end.line, 0u);
+  EXPECT_EQ(stmt->source.range.end.column, 0u);
 }
 
 TEST_F(DiscardStatementTest, Creation_WithSource) {
   auto* stmt = create<DiscardStatement>(
       Source{Source::Range{Source::Location{20, 2}, Source::Location{20, 5}}});
-  EXPECT_EQ(stmt->source().range.begin.line, 20u);
-  EXPECT_EQ(stmt->source().range.begin.column, 2u);
-  EXPECT_EQ(stmt->source().range.end.line, 20u);
-  EXPECT_EQ(stmt->source().range.end.column, 5u);
+  EXPECT_EQ(stmt->source.range.begin.line, 20u);
+  EXPECT_EQ(stmt->source.range.begin.column, 2u);
+  EXPECT_EQ(stmt->source.range.end.line, 20u);
+  EXPECT_EQ(stmt->source.range.end.column, 5u);
 }
 
 TEST_F(DiscardStatementTest, IsDiscard) {
diff --git a/src/ast/else_statement.cc b/src/ast/else_statement.cc
index ed88bbd..8c3bd59 100644
--- a/src/ast/else_statement.cc
+++ b/src/ast/else_statement.cc
@@ -21,14 +21,14 @@
 namespace tint {
 namespace ast {
 
-ElseStatement::ElseStatement(ProgramID program_id,
-                             const Source& source,
-                             Expression* condition,
-                             BlockStatement* body)
-    : Base(program_id, source), condition_(condition), body_(body) {
-  TINT_ASSERT(AST, body_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body_, program_id);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition_, program_id);
+ElseStatement::ElseStatement(ProgramID pid,
+                             const Source& src,
+                             Expression* cond,
+                             BlockStatement* b)
+    : Base(pid, src), condition(cond), body(b) {
+  TINT_ASSERT(AST, body);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition, program_id);
 }
 
 ElseStatement::ElseStatement(ElseStatement&&) = default;
@@ -37,9 +37,9 @@
 
 ElseStatement* ElseStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* cond = ctx->Clone(condition_);
-  auto* b = ctx->Clone(body_);
+  auto src = ctx->Clone(source);
+  auto* cond = ctx->Clone(condition);
+  auto* b = ctx->Clone(body);
   return ctx->dst->create<ElseStatement>(src, cond, b);
 }
 
diff --git a/src/ast/else_statement.h b/src/ast/else_statement.h
index 26a03c5..5cdc344 100644
--- a/src/ast/else_statement.h
+++ b/src/ast/else_statement.h
@@ -27,39 +27,32 @@
 class ElseStatement : public Castable<ElseStatement, Statement> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source information
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param condition the else condition
   /// @param body the else body
-  ElseStatement(ProgramID program_id,
-                const Source& source,
+  ElseStatement(ProgramID pid,
+                const Source& src,
                 Expression* condition,
                 BlockStatement* body);
   /// Move constructor
   ElseStatement(ElseStatement&&);
   ~ElseStatement() override;
 
-  /// @returns the else condition or nullptr if none set
-  Expression* condition() const { return condition_; }
-  /// @returns true if the else has a condition
-  bool HasCondition() const { return condition_ != nullptr; }
-
-  /// @returns the else body
-  const BlockStatement* body() const { return body_; }
-  /// @returns the else body
-  BlockStatement* body() { return body_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   ElseStatement* Clone(CloneContext* ctx) const override;
 
+  /// The else condition or nullptr if none set
+  Expression* const condition;
+
+  /// The else body
+  BlockStatement* const body;
+
  private:
   ElseStatement(const ElseStatement&) = delete;
-
-  Expression* const condition_;
-  BlockStatement* const body_;
 };
 
 /// A list of else statements
diff --git a/src/ast/else_statement_test.cc b/src/ast/else_statement_test.cc
index 5f3e697..11c4828 100644
--- a/src/ast/else_statement_test.cc
+++ b/src/ast/else_statement_test.cc
@@ -28,18 +28,18 @@
   auto* body = create<BlockStatement>(StatementList{
       create<DiscardStatement>(),
   });
-  auto* discard = body->get(0);
+  auto* discard = body->statements[0];
 
   auto* e = create<ElseStatement>(cond, body);
-  EXPECT_EQ(e->condition(), cond);
-  ASSERT_EQ(e->body()->size(), 1u);
-  EXPECT_EQ(e->body()->get(0), discard);
+  EXPECT_EQ(e->condition, cond);
+  ASSERT_EQ(e->body->statements.size(), 1u);
+  EXPECT_EQ(e->body->statements[0], discard);
 }
 
 TEST_F(ElseStatementTest, Creation_WithSource) {
   auto* e = create<ElseStatement>(Source{Source::Location{20, 2}}, Expr(true),
                                   Block());
-  auto src = e->source();
+  auto src = e->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
@@ -52,12 +52,12 @@
 TEST_F(ElseStatementTest, HasCondition) {
   auto* cond = Expr(true);
   auto* e = create<ElseStatement>(cond, Block());
-  EXPECT_TRUE(e->HasCondition());
+  EXPECT_TRUE(e->condition);
 }
 
 TEST_F(ElseStatementTest, HasContition_NullCondition) {
   auto* e = create<ElseStatement>(nullptr, Block());
-  EXPECT_FALSE(e->HasCondition());
+  EXPECT_FALSE(e->condition);
 }
 
 TEST_F(ElseStatementTest, Assert_Null_Body) {
diff --git a/src/ast/expression.cc b/src/ast/expression.cc
index 710e79d..304bc48 100644
--- a/src/ast/expression.cc
+++ b/src/ast/expression.cc
@@ -22,17 +22,11 @@
 namespace tint {
 namespace ast {
 
-Expression::Expression(ProgramID program_id, const Source& source)
-    : Base(program_id, source) {}
+Expression::Expression(ProgramID pid, const Source& src) : Base(pid, src) {}
 
 Expression::Expression(Expression&&) = default;
 
 Expression::~Expression() = default;
 
-std::string Expression::result_type_str(const sem::Info& sem) const {
-  auto* sem_expr = sem.Get(this);
-  return sem_expr ? sem_expr->Type()->type_name() : "not set";
-}
-
 }  // namespace ast
 }  // namespace tint
diff --git a/src/ast/expression.h b/src/ast/expression.h
index 0db419f..a319f16 100644
--- a/src/ast/expression.h
+++ b/src/ast/expression.h
@@ -31,17 +31,12 @@
 
  protected:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of the expression
-  Expression(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  Expression(ProgramID pid, const Source& src);
   /// Move constructor
   Expression(Expression&&);
 
-  /// @param sem the semantic info for the program
-  /// @returns a string representation of the result type or 'not set' if no
-  /// result type present
-  std::string result_type_str(const sem::Info& sem) const;
-
  private:
   Expression(const Expression&) = delete;
 };
diff --git a/src/ast/external_texture.cc b/src/ast/external_texture.cc
index 16376b6..cdd120c 100644
--- a/src/ast/external_texture.cc
+++ b/src/ast/external_texture.cc
@@ -22,8 +22,8 @@
 namespace ast {
 
 // ExternalTexture::ExternalTexture() : Base(ast::TextureDimension::k2d) {}
-ExternalTexture::ExternalTexture(ProgramID program_id, const Source& source)
-    : Base(program_id, source, ast::TextureDimension::k2d) {}
+ExternalTexture::ExternalTexture(ProgramID pid, const Source& src)
+    : Base(pid, src, ast::TextureDimension::k2d) {}
 
 ExternalTexture::ExternalTexture(ExternalTexture&&) = default;
 
diff --git a/src/ast/external_texture.h b/src/ast/external_texture.h
index 38d1791..250f466 100644
--- a/src/ast/external_texture.h
+++ b/src/ast/external_texture.h
@@ -26,9 +26,9 @@
 class ExternalTexture : public Castable<ExternalTexture, Texture> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
-  ExternalTexture(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  ExternalTexture(ProgramID pid, const Source& src);
 
   /// Move constructor
   ExternalTexture(ExternalTexture&&);
diff --git a/src/ast/external_texture_test.cc b/src/ast/external_texture_test.cc
index 7cd7220..a9a80fb 100644
--- a/src/ast/external_texture_test.cc
+++ b/src/ast/external_texture_test.cc
@@ -33,7 +33,7 @@
 
 TEST_F(AstExternalTextureTest, Dim) {
   auto* ty = create<ExternalTexture>();
-  EXPECT_EQ(ty->dim(), ast::TextureDimension::k2d);
+  EXPECT_EQ(ty->dim, ast::TextureDimension::k2d);
 }
 
 TEST_F(AstExternalTextureTest, FriendlyName) {
diff --git a/src/ast/f32.cc b/src/ast/f32.cc
index 039cf7f..cc5f0d1 100644
--- a/src/ast/f32.cc
+++ b/src/ast/f32.cc
@@ -21,8 +21,7 @@
 namespace tint {
 namespace ast {
 
-F32::F32(ProgramID program_id, const Source& source)
-    : Base(program_id, source) {}
+F32::F32(ProgramID pid, const Source& src) : Base(pid, src) {}
 
 F32::F32(F32&&) = default;
 
@@ -33,7 +32,7 @@
 }
 
 F32* F32::Clone(CloneContext* ctx) const {
-  auto src = ctx->Clone(source());
+  auto src = ctx->Clone(source);
   return ctx->dst->create<F32>(src);
 }
 
diff --git a/src/ast/f32.h b/src/ast/f32.h
index 1e0d4c6..804ea55 100644
--- a/src/ast/f32.h
+++ b/src/ast/f32.h
@@ -26,9 +26,9 @@
 class F32 : public Castable<F32, Type> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
-  F32(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  F32(ProgramID pid, const Source& src);
   /// Move constructor
   F32(F32&&);
   ~F32() override;
diff --git a/src/ast/fallthrough_statement.cc b/src/ast/fallthrough_statement.cc
index 4fcc2f7..cac4d86 100644
--- a/src/ast/fallthrough_statement.cc
+++ b/src/ast/fallthrough_statement.cc
@@ -21,9 +21,8 @@
 namespace tint {
 namespace ast {
 
-FallthroughStatement::FallthroughStatement(ProgramID program_id,
-                                           const Source& source)
-    : Base(program_id, source) {}
+FallthroughStatement::FallthroughStatement(ProgramID pid, const Source& src)
+    : Base(pid, src) {}
 
 FallthroughStatement::FallthroughStatement(FallthroughStatement&&) = default;
 
@@ -31,7 +30,7 @@
 
 FallthroughStatement* FallthroughStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
+  auto src = ctx->Clone(source);
   return ctx->dst->create<FallthroughStatement>(src);
 }
 
diff --git a/src/ast/fallthrough_statement.h b/src/ast/fallthrough_statement.h
index 7976b2b..026a907 100644
--- a/src/ast/fallthrough_statement.h
+++ b/src/ast/fallthrough_statement.h
@@ -24,9 +24,9 @@
 class FallthroughStatement : public Castable<FallthroughStatement, Statement> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source information
-  FallthroughStatement(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  FallthroughStatement(ProgramID pid, const Source& src);
   /// Move constructor
   FallthroughStatement(FallthroughStatement&&);
   ~FallthroughStatement() override;
diff --git a/src/ast/fallthrough_statement_test.cc b/src/ast/fallthrough_statement_test.cc
index 9081a8d..95f136e 100644
--- a/src/ast/fallthrough_statement_test.cc
+++ b/src/ast/fallthrough_statement_test.cc
@@ -24,15 +24,15 @@
 
 TEST_F(FallthroughStatementTest, Creation) {
   auto* stmt = create<FallthroughStatement>();
-  EXPECT_EQ(stmt->source().range.begin.line, 0u);
-  EXPECT_EQ(stmt->source().range.begin.column, 0u);
-  EXPECT_EQ(stmt->source().range.end.line, 0u);
-  EXPECT_EQ(stmt->source().range.end.column, 0u);
+  EXPECT_EQ(stmt->source.range.begin.line, 0u);
+  EXPECT_EQ(stmt->source.range.begin.column, 0u);
+  EXPECT_EQ(stmt->source.range.end.line, 0u);
+  EXPECT_EQ(stmt->source.range.end.column, 0u);
 }
 
 TEST_F(FallthroughStatementTest, Creation_WithSource) {
   auto* stmt = create<FallthroughStatement>(Source{Source::Location{20, 2}});
-  auto src = stmt->source();
+  auto src = stmt->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/float_literal.cc b/src/ast/float_literal.cc
index 57cd430..94bc68e 100644
--- a/src/ast/float_literal.cc
+++ b/src/ast/float_literal.cc
@@ -23,25 +23,15 @@
 namespace tint {
 namespace ast {
 
-FloatLiteral::FloatLiteral(ProgramID program_id,
-                           const Source& source,
-                           float value)
-    : Base(program_id, source), value_(value) {}
+FloatLiteral::FloatLiteral(ProgramID pid, const Source& src, float val)
+    : Base(pid, src), value(val) {}
 
 FloatLiteral::~FloatLiteral() = default;
 
-std::string FloatLiteral::name() const {
-  std::ostringstream out;
-  out.flags(out.flags() | std::ios_base::showpoint);
-  out.precision(std::numeric_limits<float>::max_digits10);
-  out << "__float" << value_;
-  return out.str();
-}
-
 FloatLiteral* FloatLiteral::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<FloatLiteral>(src, value_);
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<FloatLiteral>(src, value);
 }
 
 }  // namespace ast
diff --git a/src/ast/float_literal.h b/src/ast/float_literal.h
index 5453430..990b7e4 100644
--- a/src/ast/float_literal.h
+++ b/src/ast/float_literal.h
@@ -26,26 +26,20 @@
 class FloatLiteral : public Castable<FloatLiteral, Literal> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the input source
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param value the float literals value
-  FloatLiteral(ProgramID program_id, const Source& source, float value);
+  FloatLiteral(ProgramID pid, const Source& src, float value);
   ~FloatLiteral() override;
 
-  /// @returns the float literal value
-  float value() const { return value_; }
-
-  /// @returns the name for this literal. This name is unique to this value.
-  std::string name() const override;
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   FloatLiteral* Clone(CloneContext* ctx) const override;
 
- private:
-  float const value_;
+  /// The float literal value
+  float const value;
 };
 
 }  // namespace ast
diff --git a/src/ast/float_literal_test.cc b/src/ast/float_literal_test.cc
index a6483a7..a89f2ee 100644
--- a/src/ast/float_literal_test.cc
+++ b/src/ast/float_literal_test.cc
@@ -23,12 +23,7 @@
 TEST_F(FloatLiteralTest, Value) {
   auto* f = create<FloatLiteral>(47.2f);
   ASSERT_TRUE(f->Is<FloatLiteral>());
-  EXPECT_EQ(f->value(), 47.2f);
-}
-
-TEST_F(FloatLiteralTest, ToName) {
-  auto* f = create<FloatLiteral>(42.1f);
-  EXPECT_EQ(f->name(), "__float42.0999985");
+  EXPECT_EQ(f->value, 47.2f);
 }
 
 }  // namespace
diff --git a/src/ast/for_loop_statement.cc b/src/ast/for_loop_statement.cc
index 50d8184..a1eab18 100644
--- a/src/ast/for_loop_statement.cc
+++ b/src/ast/for_loop_statement.cc
@@ -21,23 +21,23 @@
 namespace tint {
 namespace ast {
 
-ForLoopStatement::ForLoopStatement(ProgramID program_id,
-                                   const Source& source,
-                                   Statement* initializer,
-                                   Expression* condition,
-                                   Statement* continuing,
-                                   BlockStatement* body)
-    : Base(program_id, source),
-      initializer_(initializer),
-      condition_(condition),
-      continuing_(continuing),
-      body_(body) {
-  TINT_ASSERT(AST, body_);
+ForLoopStatement::ForLoopStatement(ProgramID pid,
+                                   const Source& src,
+                                   Statement* init,
+                                   Expression* cond,
+                                   Statement* cont,
+                                   BlockStatement* b)
+    : Base(pid, src),
+      initializer(init),
+      condition(cond),
+      continuing(cont),
+      body(b) {
+  TINT_ASSERT(AST, body);
 
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, initializer_, program_id);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition_, program_id);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, continuing_, program_id);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body_, program_id);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, initializer, program_id);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition, program_id);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, continuing, program_id);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
 }
 
 ForLoopStatement::ForLoopStatement(ForLoopStatement&&) = default;
@@ -46,12 +46,12 @@
 
 ForLoopStatement* ForLoopStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
+  auto src = ctx->Clone(source);
 
-  auto* init = ctx->Clone(initializer_);
-  auto* cond = ctx->Clone(condition_);
-  auto* cont = ctx->Clone(continuing_);
-  auto* b = ctx->Clone(body_);
+  auto* init = ctx->Clone(initializer);
+  auto* cond = ctx->Clone(condition);
+  auto* cont = ctx->Clone(continuing);
+  auto* b = ctx->Clone(body);
   return ctx->dst->create<ForLoopStatement>(src, init, cond, cont, b);
 }
 
diff --git a/src/ast/for_loop_statement.h b/src/ast/for_loop_statement.h
index e5dbcc7..2dcd167 100644
--- a/src/ast/for_loop_statement.h
+++ b/src/ast/for_loop_statement.h
@@ -42,39 +42,26 @@
   ForLoopStatement(ForLoopStatement&&);
   ~ForLoopStatement() override;
 
-  /// @returns the initializer statement
-  const Statement* initializer() const { return initializer_; }
-  /// @returns the initializer statement
-  Statement* initializer() { return initializer_; }
-
-  /// @returns the condition expression
-  const Expression* condition() const { return condition_; }
-  /// @returns the condition expression
-  Expression* condition() { return condition_; }
-
-  /// @returns the continuing statement
-  const Statement* continuing() const { return continuing_; }
-  /// @returns the continuing statement
-  Statement* continuing() { return continuing_; }
-
-  /// @returns the loop body block
-  const BlockStatement* body() const { return body_; }
-  /// @returns the loop body block
-  BlockStatement* body() { return body_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   ForLoopStatement* Clone(CloneContext* ctx) const override;
 
+  /// The initializer statement
+  Statement* const initializer;
+
+  /// The condition expression
+  Expression* const condition;
+
+  /// The continuing statement
+  Statement* const continuing;
+
+  /// The loop body block
+  BlockStatement* const body;
+
  private:
   ForLoopStatement(const ForLoopStatement&) = delete;
-
-  Statement* const initializer_;
-  Expression* const condition_;
-  Statement* const continuing_;
-  BlockStatement* const body_;
 };
 
 }  // namespace ast
diff --git a/src/ast/for_loop_statement_test.cc b/src/ast/for_loop_statement_test.cc
index 8217e3f..73f70fa 100644
--- a/src/ast/for_loop_statement_test.cc
+++ b/src/ast/for_loop_statement_test.cc
@@ -30,16 +30,16 @@
   auto* body = Block(Return());
   auto* l = For(init, cond, cont, body);
 
-  EXPECT_EQ(l->initializer(), init);
-  EXPECT_EQ(l->condition(), cond);
-  EXPECT_EQ(l->continuing(), cont);
-  EXPECT_EQ(l->body(), body);
+  EXPECT_EQ(l->initializer, init);
+  EXPECT_EQ(l->condition, cond);
+  EXPECT_EQ(l->continuing, cont);
+  EXPECT_EQ(l->body, body);
 }
 
 TEST_F(ForLoopStatementTest, Creation_WithSource) {
   auto* body = Block(Return());
   auto* l = For(Source{{20u, 2u}}, nullptr, nullptr, nullptr, body);
-  auto src = l->source();
+  auto src = l->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
@@ -47,7 +47,7 @@
 TEST_F(ForLoopStatementTest, Creation_Null_InitCondCont) {
   auto* body = Block(Return());
   auto* l = For(nullptr, nullptr, nullptr, body);
-  EXPECT_EQ(l->body(), body);
+  EXPECT_EQ(l->body, body);
 }
 
 TEST_F(ForLoopStatementTest, Assert_Null_Body) {
diff --git a/src/ast/function.cc b/src/ast/function.cc
index d6dfc9e..fa44f3e 100644
--- a/src/ast/function.cc
+++ b/src/ast/function.cc
@@ -23,33 +23,33 @@
 namespace tint {
 namespace ast {
 
-Function::Function(ProgramID program_id,
-                   const Source& source,
-                   Symbol symbol,
-                   VariableList params,
-                   ast::Type* return_type,
-                   BlockStatement* body,
-                   DecorationList decorations,
-                   DecorationList return_type_decorations)
-    : Base(program_id, source),
-      symbol_(symbol),
-      params_(std::move(params)),
-      return_type_(return_type),
-      body_(body),
-      decorations_(std::move(decorations)),
-      return_type_decorations_(std::move(return_type_decorations)) {
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol_, program_id);
+Function::Function(ProgramID pid,
+                   const Source& src,
+                   Symbol sym,
+                   VariableList parameters,
+                   ast::Type* return_ty,
+                   BlockStatement* b,
+                   DecorationList decos,
+                   DecorationList return_type_decos)
+    : Base(pid, src),
+      symbol(sym),
+      params(std::move(parameters)),
+      return_type(return_ty),
+      body(b),
+      decorations(std::move(decos)),
+      return_type_decorations(std::move(return_type_decos)) {
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol, program_id);
   TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
-  for (auto* param : params_) {
-    TINT_ASSERT(AST, param && param->is_const());
+  for (auto* param : params) {
+    TINT_ASSERT(AST, param && param->is_const);
     TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, param, program_id);
   }
-  TINT_ASSERT(AST, symbol_.IsValid());
-  TINT_ASSERT(AST, return_type_);
-  for (auto* deco : decorations_) {
+  TINT_ASSERT(AST, symbol.IsValid());
+  TINT_ASSERT(AST, return_type);
+  for (auto* deco : decorations) {
     TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, deco, program_id);
   }
-  for (auto* deco : return_type_decorations_) {
+  for (auto* deco : return_type_decorations) {
     TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, deco, program_id);
   }
 }
@@ -58,32 +58,28 @@
 
 Function::~Function() = default;
 
-PipelineStage Function::pipeline_stage() const {
-  if (auto* stage = GetDecoration<StageDecoration>(decorations_)) {
-    return stage->value();
+PipelineStage Function::PipelineStage() const {
+  if (auto* stage = GetDecoration<StageDecoration>(decorations)) {
+    return stage->stage;
   }
   return PipelineStage::kNone;
 }
 
-const Statement* Function::get_last_statement() const {
-  return body_->last();
-}
-
 Function* Function::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto sym = ctx->Clone(symbol());
-  auto p = ctx->Clone(params_);
-  auto* ret = ctx->Clone(return_type_);
-  auto* b = ctx->Clone(body_);
-  auto decos = ctx->Clone(decorations_);
-  auto ret_decos = ctx->Clone(return_type_decorations_);
+  auto src = ctx->Clone(source);
+  auto sym = ctx->Clone(symbol);
+  auto p = ctx->Clone(params);
+  auto* ret = ctx->Clone(return_type);
+  auto* b = ctx->Clone(body);
+  auto decos = ctx->Clone(decorations);
+  auto ret_decos = ctx->Clone(return_type_decorations);
   return ctx->dst->create<Function>(src, sym, p, ret, b, decos, ret_decos);
 }
 
 Function* FunctionList::Find(Symbol sym) const {
   for (auto* func : *this) {
-    if (func->symbol() == sym) {
+    if (func->symbol == sym) {
       return func;
     }
   }
@@ -92,7 +88,7 @@
 
 Function* FunctionList::Find(Symbol sym, PipelineStage stage) const {
   for (auto* func : *this) {
-    if (func->symbol() == sym && func->pipeline_stage() == stage) {
+    if (func->symbol == sym && func->PipelineStage() == stage) {
       return func;
     }
   }
@@ -101,7 +97,7 @@
 
 bool FunctionList::HasStage(ast::PipelineStage stage) const {
   for (auto* func : *this) {
-    if (func->pipeline_stage() == stage) {
+    if (func->PipelineStage() == stage) {
       return true;
     }
   }
diff --git a/src/ast/function.h b/src/ast/function.h
index 2cc83e9..2e60d55 100644
--- a/src/ast/function.h
+++ b/src/ast/function.h
@@ -57,36 +57,11 @@
 
   ~Function() override;
 
-  /// @returns the function symbol
-  Symbol symbol() const { return symbol_; }
-  /// @returns the function params
-  const VariableList& params() const { return params_; }
-
-  /// @returns the decorations attached to this function
-  const DecorationList& decorations() const { return decorations_; }
-
   /// @returns the functions pipeline stage or None if not set
-  PipelineStage pipeline_stage() const;
+  ast::PipelineStage PipelineStage() const;
 
   /// @returns true if this function is an entry point
-  bool IsEntryPoint() const { return pipeline_stage() != PipelineStage::kNone; }
-
-  /// @returns the function return type.
-  ast::Type* return_type() const { return return_type_; }
-
-  /// @returns the decorations attached to the function return type.
-  const DecorationList& return_type_decorations() const {
-    return return_type_decorations_;
-  }
-
-  /// @returns a pointer to the last statement of the function or nullptr if
-  // function is empty
-  const Statement* get_last_statement() const;
-
-  /// @returns the function body
-  const BlockStatement* body() const { return body_; }
-  /// @returns the function body
-  BlockStatement* body() { return body_; }
+  bool IsEntryPoint() const { return PipelineStage() != PipelineStage::kNone; }
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -94,15 +69,26 @@
   /// @return the newly cloned node
   Function* Clone(CloneContext* ctx) const override;
 
+  /// The function symbol
+  Symbol const symbol;
+
+  /// The function params
+  VariableList const params;
+
+  /// The function return type
+  ast::Type* const return_type;
+
+  /// The function body
+  BlockStatement* const body;
+
+  /// The decorations attached to this function
+  DecorationList const decorations;
+
+  /// The decorations attached to the function return type.
+  DecorationList const return_type_decorations;
+
  private:
   Function(const Function&) = delete;
-
-  Symbol const symbol_;
-  VariableList const params_;
-  ast::Type* const return_type_;
-  BlockStatement* const body_;
-  DecorationList const decorations_;
-  DecorationList const return_type_decorations_;
 };
 
 /// A list of functions
diff --git a/src/ast/function_test.cc b/src/ast/function_test.cc
index 839e9b2..85e77d2 100644
--- a/src/ast/function_test.cc
+++ b/src/ast/function_test.cc
@@ -30,10 +30,10 @@
   auto* var = params[0];
 
   auto* f = Func("func", params, ty.void_(), StatementList{}, DecorationList{});
-  EXPECT_EQ(f->symbol(), Symbols().Get("func"));
-  ASSERT_EQ(f->params().size(), 1u);
-  EXPECT_TRUE(f->return_type()->Is<ast::Void>());
-  EXPECT_EQ(f->params()[0], var);
+  EXPECT_EQ(f->symbol, Symbols().Get("func"));
+  ASSERT_EQ(f->params.size(), 1u);
+  EXPECT_TRUE(f->return_type->Is<ast::Void>());
+  EXPECT_EQ(f->params[0], var);
 }
 
 TEST_F(FunctionTest, Creation_WithSource) {
@@ -42,7 +42,7 @@
 
   auto* f = Func(Source{Source::Location{20, 2}}, "func", params, ty.void_(),
                  StatementList{}, DecorationList{});
-  auto src = f->source();
+  auto src = f->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
@@ -139,22 +139,6 @@
       "internal compiler error");
 }
 
-TEST_F(FunctionTest, GetLastStatement) {
-  VariableList params;
-  auto* stmt = create<DiscardStatement>();
-  auto* f =
-      Func("func", params, ty.void_(), StatementList{stmt}, DecorationList{});
-
-  EXPECT_EQ(f->get_last_statement(), stmt);
-}
-
-TEST_F(FunctionTest, GetLastStatement_nullptr) {
-  VariableList params;
-  auto* f = Func("func", params, ty.void_(), StatementList{}, DecorationList{});
-
-  EXPECT_EQ(f->get_last_statement(), nullptr);
-}
-
 using FunctionListTest = TestHelper;
 
 TEST_F(FunctionListTest, FindSymbol) {
diff --git a/src/ast/group_decoration.cc b/src/ast/group_decoration.cc
index c72f444..571794e 100644
--- a/src/ast/group_decoration.cc
+++ b/src/ast/group_decoration.cc
@@ -23,21 +23,19 @@
 namespace tint {
 namespace ast {
 
-GroupDecoration::GroupDecoration(ProgramID program_id,
-                                 const Source& source,
-                                 uint32_t val)
-    : Base(program_id, source), value_(val) {}
+GroupDecoration::GroupDecoration(ProgramID pid, const Source& src, uint32_t val)
+    : Base(pid, src), value(val) {}
 
 GroupDecoration::~GroupDecoration() = default;
 
-std::string GroupDecoration::name() const {
+std::string GroupDecoration::Name() const {
   return "group";
 }
 
 GroupDecoration* GroupDecoration::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<GroupDecoration>(src, value_);
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<GroupDecoration>(src, value);
 }
 
 }  // namespace ast
diff --git a/src/ast/group_decoration.h b/src/ast/group_decoration.h
index 1d86128..de14126 100644
--- a/src/ast/group_decoration.h
+++ b/src/ast/group_decoration.h
@@ -26,17 +26,14 @@
 class GroupDecoration : public Castable<GroupDecoration, Decoration> {
  public:
   /// constructor
-  /// @param program_id the identifier of the program that owns this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param value the group value
-  /// @param source the source of this decoration
-  GroupDecoration(ProgramID program_id, const Source& source, uint32_t value);
+  GroupDecoration(ProgramID pid, const Source& src, uint32_t value);
   ~GroupDecoration() override;
 
-  /// @returns the group value
-  uint32_t value() const { return value_; }
-
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -44,8 +41,8 @@
   /// @return the newly cloned node
   GroupDecoration* Clone(CloneContext* ctx) const override;
 
- private:
-  uint32_t const value_;
+  /// The group value
+  uint32_t const value;
 };
 
 }  // namespace ast
diff --git a/src/ast/group_decoration_test.cc b/src/ast/group_decoration_test.cc
index 7398b75..662d88c 100644
--- a/src/ast/group_decoration_test.cc
+++ b/src/ast/group_decoration_test.cc
@@ -23,7 +23,7 @@
 
 TEST_F(GroupDecorationTest, Creation) {
   auto* d = create<GroupDecoration>(2);
-  EXPECT_EQ(2u, d->value());
+  EXPECT_EQ(2u, d->value);
 }
 
 }  // namespace
diff --git a/src/ast/i32.cc b/src/ast/i32.cc
index e59ab25..b9145d3 100644
--- a/src/ast/i32.cc
+++ b/src/ast/i32.cc
@@ -21,8 +21,7 @@
 namespace tint {
 namespace ast {
 
-I32::I32(ProgramID program_id, const Source& source)
-    : Base(program_id, source) {}
+I32::I32(ProgramID pid, const Source& src) : Base(pid, src) {}
 
 I32::I32(I32&&) = default;
 
@@ -33,7 +32,7 @@
 }
 
 I32* I32::Clone(CloneContext* ctx) const {
-  auto src = ctx->Clone(source());
+  auto src = ctx->Clone(source);
   return ctx->dst->create<I32>(src);
 }
 
diff --git a/src/ast/i32.h b/src/ast/i32.h
index 5134b8b..63e66e4 100644
--- a/src/ast/i32.h
+++ b/src/ast/i32.h
@@ -26,9 +26,9 @@
 class I32 : public Castable<I32, Type> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
-  I32(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  I32(ProgramID pid, const Source& src);
   /// Move constructor
   I32(I32&&);
   ~I32() override;
diff --git a/src/ast/identifier_expression.cc b/src/ast/identifier_expression.cc
index c316062..da80ff0 100644
--- a/src/ast/identifier_expression.cc
+++ b/src/ast/identifier_expression.cc
@@ -21,12 +21,12 @@
 namespace tint {
 namespace ast {
 
-IdentifierExpression::IdentifierExpression(ProgramID program_id,
-                                           const Source& source,
+IdentifierExpression::IdentifierExpression(ProgramID pid,
+                                           const Source& src,
                                            Symbol sym)
-    : Base(program_id, source), sym_(sym) {
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, sym_, program_id);
-  TINT_ASSERT(AST, sym_.IsValid());
+    : Base(pid, src), symbol(sym) {
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol, program_id);
+  TINT_ASSERT(AST, symbol.IsValid());
 }
 
 IdentifierExpression::IdentifierExpression(IdentifierExpression&&) = default;
@@ -35,8 +35,8 @@
 
 IdentifierExpression* IdentifierExpression::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto sym = ctx->Clone(symbol());
+  auto src = ctx->Clone(source);
+  auto sym = ctx->Clone(symbol);
   return ctx->dst->create<IdentifierExpression>(src, sym);
 }
 
diff --git a/src/ast/identifier_expression.h b/src/ast/identifier_expression.h
index b47a150..b60a5ad 100644
--- a/src/ast/identifier_expression.h
+++ b/src/ast/identifier_expression.h
@@ -24,27 +24,25 @@
 class IdentifierExpression : public Castable<IdentifierExpression, Expression> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param sym the symbol for the identifier
-  IdentifierExpression(ProgramID program_id, const Source& source, Symbol sym);
+  IdentifierExpression(ProgramID pid, const Source& src, Symbol sym);
   /// Move constructor
   IdentifierExpression(IdentifierExpression&&);
   ~IdentifierExpression() override;
 
-  /// @returns the symbol for the identifier
-  Symbol symbol() const { return sym_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   IdentifierExpression* Clone(CloneContext* ctx) const override;
 
+  /// The symbol for the identifier
+  Symbol const symbol;
+
  private:
   IdentifierExpression(const IdentifierExpression&) = delete;
-
-  Symbol const sym_;
 };
 
 }  // namespace ast
diff --git a/src/ast/identifier_expression_test.cc b/src/ast/identifier_expression_test.cc
index 6d22969..ad6dff5 100644
--- a/src/ast/identifier_expression_test.cc
+++ b/src/ast/identifier_expression_test.cc
@@ -23,14 +23,14 @@
 
 TEST_F(IdentifierExpressionTest, Creation) {
   auto* i = Expr("ident");
-  EXPECT_EQ(i->symbol(), Symbol(1, ID()));
+  EXPECT_EQ(i->symbol, Symbol(1, ID()));
 }
 
 TEST_F(IdentifierExpressionTest, Creation_WithSource) {
   auto* i = Expr(Source{Source::Location{20, 2}}, "ident");
-  EXPECT_EQ(i->symbol(), Symbol(1, ID()));
+  EXPECT_EQ(i->symbol, Symbol(1, ID()));
 
-  auto src = i->source();
+  auto src = i->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/if_statement.cc b/src/ast/if_statement.cc
index 0d4db22..f4120d7 100644
--- a/src/ast/if_statement.cc
+++ b/src/ast/if_statement.cc
@@ -21,20 +21,20 @@
 namespace tint {
 namespace ast {
 
-IfStatement::IfStatement(ProgramID program_id,
-                         const Source& source,
-                         Expression* condition,
-                         BlockStatement* body,
+IfStatement::IfStatement(ProgramID pid,
+                         const Source& src,
+                         Expression* cond,
+                         BlockStatement* b,
                          ElseStatementList else_stmts)
-    : Base(program_id, source),
-      condition_(condition),
-      body_(body),
-      else_statements_(std::move(else_stmts)) {
-  TINT_ASSERT(AST, condition_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition_, program_id);
-  TINT_ASSERT(AST, body_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body_, program_id);
-  for (auto* el : else_statements_) {
+    : Base(pid, src),
+      condition(cond),
+      body(b),
+      else_statements(std::move(else_stmts)) {
+  TINT_ASSERT(AST, condition);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition, program_id);
+  TINT_ASSERT(AST, body);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
+  for (auto* el : else_statements) {
     TINT_ASSERT(AST, el);
     TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, el, program_id);
   }
@@ -46,10 +46,10 @@
 
 IfStatement* IfStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* cond = ctx->Clone(condition_);
-  auto* b = ctx->Clone(body_);
-  auto el = ctx->Clone(else_statements_);
+  auto src = ctx->Clone(source);
+  auto* cond = ctx->Clone(condition);
+  auto* b = ctx->Clone(body);
+  auto el = ctx->Clone(else_statements);
   return ctx->dst->create<IfStatement>(src, cond, b, el);
 }
 
diff --git a/src/ast/if_statement.h b/src/ast/if_statement.h
index ed12df4..f955107 100644
--- a/src/ast/if_statement.h
+++ b/src/ast/if_statement.h
@@ -26,13 +26,13 @@
 class IfStatement : public Castable<IfStatement, Statement> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source information
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param condition the if condition
   /// @param body the if body
   /// @param else_stmts the else statements
-  IfStatement(ProgramID program_id,
-              const Source& source,
+  IfStatement(ProgramID pid,
+              const Source& src,
               Expression* condition,
               BlockStatement* body,
               ElseStatementList else_stmts);
@@ -40,31 +40,23 @@
   IfStatement(IfStatement&&);
   ~IfStatement() override;
 
-  /// @returns the if condition or nullptr if none set
-  Expression* condition() const { return condition_; }
-  /// @returns the if body
-  const BlockStatement* body() const { return body_; }
-  /// @returns the if body
-  BlockStatement* body() { return body_; }
-
-  /// @returns the else statements
-  const ElseStatementList& else_statements() const { return else_statements_; }
-
-  /// @returns true if there are else statements
-  bool has_else_statements() const { return !else_statements_.empty(); }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   IfStatement* Clone(CloneContext* ctx) const override;
 
+  /// The if condition or nullptr if none set
+  Expression* const condition;
+
+  /// The if body
+  BlockStatement* const body;
+
+  /// The else statements
+  ElseStatementList const else_statements;
+
  private:
   IfStatement(const IfStatement&) = delete;
-
-  Expression* const condition_;
-  BlockStatement* const body_;
-  ElseStatementList const else_statements_;
 };
 
 }  // namespace ast
diff --git a/src/ast/if_statement_test.cc b/src/ast/if_statement_test.cc
index c5740ce..99903ae 100644
--- a/src/ast/if_statement_test.cc
+++ b/src/ast/if_statement_test.cc
@@ -29,7 +29,7 @@
   auto* stmt = create<IfStatement>(Source{Source::Location{20, 2}}, cond,
                                    Block(create<DiscardStatement>()),
                                    ElseStatementList{});
-  auto src = stmt->source();
+  auto src = stmt->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/int_literal.cc b/src/ast/int_literal.cc
index 75dd5cd..f9659d5 100644
--- a/src/ast/int_literal.cc
+++ b/src/ast/int_literal.cc
@@ -19,10 +19,8 @@
 namespace tint {
 namespace ast {
 
-IntLiteral::IntLiteral(ProgramID program_id,
-                       const Source& source,
-                       uint32_t value)
-    : Base(program_id, source), value_(value) {}
+IntLiteral::IntLiteral(ProgramID pid, const Source& src)
+    : Base(pid, src) {}
 
 IntLiteral::~IntLiteral() = default;
 
diff --git a/src/ast/int_literal.h b/src/ast/int_literal.h
index 4a12ef6..96d55a9 100644
--- a/src/ast/int_literal.h
+++ b/src/ast/int_literal.h
@@ -25,21 +25,17 @@
  public:
   ~IntLiteral() override;
 
-  /// @returns the literal value as an i32
-  int32_t value_as_i32() const { return static_cast<int32_t>(value_); }
-
   /// @returns the literal value as a u32
-  uint32_t value_as_u32() const { return value_; }
+  virtual uint32_t ValueAsU32() const = 0;
+
+  /// @returns the literal value as an i32
+  int32_t ValueAsI32() const { return static_cast<int32_t>(ValueAsU32()); }
 
  protected:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the input source
-  /// @param value value of the literal
-  IntLiteral(ProgramID program_id, const Source& source, uint32_t value);
-
- private:
-  uint32_t const value_;
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  IntLiteral(ProgramID pid, const Source& src);
 };  // namespace ast
 
 }  // namespace ast
diff --git a/src/ast/internal_decoration.cc b/src/ast/internal_decoration.cc
index 01489f5..d3354c5 100644
--- a/src/ast/internal_decoration.cc
+++ b/src/ast/internal_decoration.cc
@@ -19,12 +19,11 @@
 namespace tint {
 namespace ast {
 
-InternalDecoration::InternalDecoration(ProgramID program_id)
-    : Base(program_id, Source{}) {}
+InternalDecoration::InternalDecoration(ProgramID pid) : Base(pid, Source{}) {}
 
 InternalDecoration::~InternalDecoration() = default;
 
-std::string InternalDecoration::name() const {
+std::string InternalDecoration::Name() const {
   return "internal";
 }
 
diff --git a/src/ast/internal_decoration.h b/src/ast/internal_decoration.h
index 7196056..eb0b814 100644
--- a/src/ast/internal_decoration.h
+++ b/src/ast/internal_decoration.h
@@ -39,7 +39,7 @@
   virtual std::string InternalName() const = 0;
 
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 };
 
 }  // namespace ast
diff --git a/src/ast/interpolate_decoration.cc b/src/ast/interpolate_decoration.cc
index 35a12f5..e3f7fae 100644
--- a/src/ast/interpolate_decoration.cc
+++ b/src/ast/interpolate_decoration.cc
@@ -23,22 +23,22 @@
 namespace tint {
 namespace ast {
 
-InterpolateDecoration::InterpolateDecoration(ProgramID program_id,
-                                             const Source& source,
-                                             InterpolationType type,
-                                             InterpolationSampling sampling)
-    : Base(program_id, source), type_(type), sampling_(sampling) {}
+InterpolateDecoration::InterpolateDecoration(ProgramID pid,
+                                             const Source& src,
+                                             InterpolationType ty,
+                                             InterpolationSampling smpl)
+    : Base(pid, src), type(ty), sampling(smpl) {}
 
 InterpolateDecoration::~InterpolateDecoration() = default;
 
-std::string InterpolateDecoration::name() const {
+std::string InterpolateDecoration::Name() const {
   return "interpolate";
 }
 
 InterpolateDecoration* InterpolateDecoration::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<InterpolateDecoration>(src, type_, sampling_);
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<InterpolateDecoration>(src, type, sampling);
 }
 
 std::ostream& operator<<(std::ostream& out, InterpolationType type) {
diff --git a/src/ast/interpolate_decoration.h b/src/ast/interpolate_decoration.h
index a219499..54883fa 100644
--- a/src/ast/interpolate_decoration.h
+++ b/src/ast/interpolate_decoration.h
@@ -34,24 +34,18 @@
     : public Castable<InterpolateDecoration, Decoration> {
  public:
   /// Create an interpolate decoration.
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this decoration
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param type the interpolation type
   /// @param sampling the interpolation sampling
-  InterpolateDecoration(ProgramID program_id,
-                        const Source& source,
+  InterpolateDecoration(ProgramID pid,
+                        const Source& src,
                         InterpolationType type,
                         InterpolationSampling sampling);
   ~InterpolateDecoration() override;
 
-  /// @returns the interpolation type
-  InterpolationType type() const { return type_; }
-
-  /// @returns the interpolation sampling
-  InterpolationSampling sampling() const { return sampling_; }
-
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -59,9 +53,11 @@
   /// @return the newly cloned node
   InterpolateDecoration* Clone(CloneContext* ctx) const override;
 
- private:
-  InterpolationType const type_;
-  InterpolationSampling const sampling_;
+  /// The interpolation type
+  InterpolationType const type;
+
+  /// The interpolation sampling
+  InterpolationSampling const sampling;
 };
 
 /// @param out the std::ostream to write to
diff --git a/src/ast/interpolate_decoration_test.cc b/src/ast/interpolate_decoration_test.cc
index d6ce1c6..cb93b0c 100644
--- a/src/ast/interpolate_decoration_test.cc
+++ b/src/ast/interpolate_decoration_test.cc
@@ -25,8 +25,8 @@
 TEST_F(InterpolateDecorationTest, Creation) {
   auto* d = create<InterpolateDecoration>(InterpolationType::kLinear,
                                           InterpolationSampling::kCenter);
-  EXPECT_EQ(InterpolationType::kLinear, d->type());
-  EXPECT_EQ(InterpolationSampling::kCenter, d->sampling());
+  EXPECT_EQ(InterpolationType::kLinear, d->type);
+  EXPECT_EQ(InterpolationSampling::kCenter, d->sampling);
 }
 
 }  // namespace
diff --git a/src/ast/intrinsic_texture_helper_test.cc b/src/ast/intrinsic_texture_helper_test.cc
index 471a802..c926f2d 100644
--- a/src/ast/intrinsic_texture_helper_test.cc
+++ b/src/ast/intrinsic_texture_helper_test.cc
@@ -134,7 +134,7 @@
   return out;
 }
 
-ast::Type* TextureOverloadCase::buildResultVectorComponentType(
+ast::Type* TextureOverloadCase::BuildResultVectorComponentType(
     ProgramBuilder* b) const {
   switch (texture_data_type) {
     case ast::intrinsic::test::TextureDataType::kF32:
@@ -149,7 +149,7 @@
   return {};
 }
 
-ast::Variable* TextureOverloadCase::buildTextureVariable(
+ast::Variable* TextureOverloadCase::BuildTextureVariable(
     ProgramBuilder* b) const {
   DecorationList decos = {
       b->create<ast::GroupDecoration>(0),
@@ -159,7 +159,7 @@
     case ast::intrinsic::test::TextureKind::kRegular:
       return b->Global("texture",
                        b->ty.sampled_texture(texture_dimension,
-                                             buildResultVectorComponentType(b)),
+                                             BuildResultVectorComponentType(b)),
                        decos);
 
     case ast::intrinsic::test::TextureKind::kDepth:
@@ -175,7 +175,7 @@
       return b->Global(
           "texture",
           b->ty.multisampled_texture(texture_dimension,
-                                     buildResultVectorComponentType(b)),
+                                     BuildResultVectorComponentType(b)),
           decos);
 
     case ast::intrinsic::test::TextureKind::kStorage: {
@@ -188,7 +188,7 @@
   return nullptr;
 }
 
-ast::Variable* TextureOverloadCase::buildSamplerVariable(
+ast::Variable* TextureOverloadCase::BuildSamplerVariable(
     ProgramBuilder* b) const {
   DecorationList decos = {
       b->create<ast::GroupDecoration>(0),
diff --git a/src/ast/intrinsic_texture_helper_test.h b/src/ast/intrinsic_texture_helper_test.h
index 0c47fa4..5f842f1 100644
--- a/src/ast/intrinsic_texture_helper_test.h
+++ b/src/ast/intrinsic_texture_helper_test.h
@@ -205,15 +205,15 @@
 
   /// @param builder the AST builder used for the test
   /// @returns the vector component type of the texture function return value
-  ast::Type* buildResultVectorComponentType(ProgramBuilder* builder) const;
+  ast::Type* BuildResultVectorComponentType(ProgramBuilder* builder) const;
   /// @param builder the AST builder used for the test
   /// @returns a variable holding the test texture, automatically registered as
   /// a global variable.
-  ast::Variable* buildTextureVariable(ProgramBuilder* builder) const;
+  ast::Variable* BuildTextureVariable(ProgramBuilder* builder) const;
   /// @param builder the AST builder used for the test
   /// @returns a Variable holding the test sampler, automatically registered as
   /// a global variable.
-  ast::Variable* buildSamplerVariable(ProgramBuilder* builder) const;
+  ast::Variable* BuildSamplerVariable(ProgramBuilder* builder) const;
 
   /// The enumerator for this overload
   ValidTextureOverload const overload;
diff --git a/src/ast/invariant_decoration.cc b/src/ast/invariant_decoration.cc
index 6425d14..cf00a5b 100644
--- a/src/ast/invariant_decoration.cc
+++ b/src/ast/invariant_decoration.cc
@@ -21,19 +21,18 @@
 namespace tint {
 namespace ast {
 
-InvariantDecoration::InvariantDecoration(ProgramID program_id,
-                                         const Source& source)
-    : Base(program_id, source) {}
+InvariantDecoration::InvariantDecoration(ProgramID pid, const Source& src)
+    : Base(pid, src) {}
 
 InvariantDecoration::~InvariantDecoration() = default;
 
-std::string InvariantDecoration::name() const {
+std::string InvariantDecoration::Name() const {
   return "invariant";
 }
 
 InvariantDecoration* InvariantDecoration::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
+  auto src = ctx->Clone(source);
   return ctx->dst->create<InvariantDecoration>(src);
 }
 
diff --git a/src/ast/invariant_decoration.h b/src/ast/invariant_decoration.h
index 290741c..5f3216d 100644
--- a/src/ast/invariant_decoration.h
+++ b/src/ast/invariant_decoration.h
@@ -26,13 +26,13 @@
 class InvariantDecoration : public Castable<InvariantDecoration, Decoration> {
  public:
   /// constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this decoration
-  InvariantDecoration(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  InvariantDecoration(ProgramID pid, const Source& src);
   ~InvariantDecoration() override;
 
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
diff --git a/src/ast/literal.cc b/src/ast/literal.cc
index 0c6e26f..6232a96 100644
--- a/src/ast/literal.cc
+++ b/src/ast/literal.cc
@@ -19,8 +19,7 @@
 namespace tint {
 namespace ast {
 
-Literal::Literal(ProgramID program_id, const Source& source)
-    : Base(program_id, source) {}
+Literal::Literal(ProgramID pid, const Source& src) : Base(pid, src) {}
 
 Literal::~Literal() = default;
 
diff --git a/src/ast/literal.h b/src/ast/literal.h
index 0b86d62..df8db02 100644
--- a/src/ast/literal.h
+++ b/src/ast/literal.h
@@ -27,14 +27,11 @@
  public:
   ~Literal() override;
 
-  /// @returns the name for this literal. This name is unique to this value.
-  virtual std::string name() const = 0;
-
  protected:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the input source
-  Literal(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the input source
+  Literal(ProgramID pid, const Source& src);
 };
 
 }  // namespace ast
diff --git a/src/ast/location_decoration.cc b/src/ast/location_decoration.cc
index ff5b9c9..5db7e36 100644
--- a/src/ast/location_decoration.cc
+++ b/src/ast/location_decoration.cc
@@ -23,21 +23,21 @@
 namespace tint {
 namespace ast {
 
-LocationDecoration::LocationDecoration(ProgramID program_id,
-                                       const Source& source,
+LocationDecoration::LocationDecoration(ProgramID pid,
+                                       const Source& src,
                                        uint32_t val)
-    : Base(program_id, source), value_(val) {}
+    : Base(pid, src), value(val) {}
 
 LocationDecoration::~LocationDecoration() = default;
 
-std::string LocationDecoration::name() const {
+std::string LocationDecoration::Name() const {
   return "location";
 }
 
 LocationDecoration* LocationDecoration::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<LocationDecoration>(src, value_);
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<LocationDecoration>(src, value);
 }
 
 }  // namespace ast
diff --git a/src/ast/location_decoration.h b/src/ast/location_decoration.h
index 7e8eef8..d547874 100644
--- a/src/ast/location_decoration.h
+++ b/src/ast/location_decoration.h
@@ -26,19 +26,14 @@
 class LocationDecoration : public Castable<LocationDecoration, Decoration> {
  public:
   /// constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this decoration
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param value the location value
-  LocationDecoration(ProgramID program_id,
-                     const Source& source,
-                     uint32_t value);
+  LocationDecoration(ProgramID pid, const Source& src, uint32_t value);
   ~LocationDecoration() override;
 
-  /// @returns the location value
-  uint32_t value() const { return value_; }
-
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -46,8 +41,8 @@
   /// @return the newly cloned node
   LocationDecoration* Clone(CloneContext* ctx) const override;
 
- private:
-  uint32_t const value_;
+  /// The location value
+  uint32_t const value;
 };
 
 }  // namespace ast
diff --git a/src/ast/location_decoration_test.cc b/src/ast/location_decoration_test.cc
index 66a57e1..3868463 100644
--- a/src/ast/location_decoration_test.cc
+++ b/src/ast/location_decoration_test.cc
@@ -23,7 +23,7 @@
 
 TEST_F(LocationDecorationTest, Creation) {
   auto* d = create<LocationDecoration>(2);
-  EXPECT_EQ(2u, d->value());
+  EXPECT_EQ(2u, d->value);
 }
 
 }  // namespace
diff --git a/src/ast/loop_statement.cc b/src/ast/loop_statement.cc
index cbbca68..e01392e 100644
--- a/src/ast/loop_statement.cc
+++ b/src/ast/loop_statement.cc
@@ -21,14 +21,14 @@
 namespace tint {
 namespace ast {
 
-LoopStatement::LoopStatement(ProgramID program_id,
-                             const Source& source,
-                             BlockStatement* body,
-                             BlockStatement* continuing)
-    : Base(program_id, source), body_(body), continuing_(continuing) {
-  TINT_ASSERT(AST, body_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body_, program_id);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, continuing_, program_id);
+LoopStatement::LoopStatement(ProgramID pid,
+                             const Source& src,
+                             BlockStatement* b,
+                             BlockStatement* cont)
+    : Base(pid, src), body(b), continuing(cont) {
+  TINT_ASSERT(AST, body);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body, program_id);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, continuing, program_id);
 }
 
 LoopStatement::LoopStatement(LoopStatement&&) = default;
@@ -37,9 +37,9 @@
 
 LoopStatement* LoopStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* b = ctx->Clone(body_);
-  auto* cont = ctx->Clone(continuing_);
+  auto src = ctx->Clone(source);
+  auto* b = ctx->Clone(body);
+  auto* cont = ctx->Clone(continuing);
   return ctx->dst->create<LoopStatement>(src, b, cont);
 }
 
diff --git a/src/ast/loop_statement.h b/src/ast/loop_statement.h
index 9ddafe2..062ad39 100644
--- a/src/ast/loop_statement.h
+++ b/src/ast/loop_statement.h
@@ -36,31 +36,20 @@
   LoopStatement(LoopStatement&&);
   ~LoopStatement() override;
 
-  /// @returns the body statements
-  const BlockStatement* body() const { return body_; }
-  /// @returns the body statements
-  BlockStatement* body() { return body_; }
-
-  /// @returns the continuing statements
-  const BlockStatement* continuing() const { return continuing_; }
-  /// @returns the continuing statements
-  BlockStatement* continuing() { return continuing_; }
-  /// @returns true if there are continuing statements in the loop
-  bool has_continuing() const {
-    return continuing_ != nullptr && !continuing_->empty();
-  }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   LoopStatement* Clone(CloneContext* ctx) const override;
 
+  /// The loop body
+  BlockStatement* const body;
+
+  /// The continuing statements
+  BlockStatement* const continuing;
+
  private:
   LoopStatement(const LoopStatement&) = delete;
-
-  BlockStatement* const body_;
-  BlockStatement* const continuing_;
 };
 
 }  // namespace ast
diff --git a/src/ast/loop_statement_test.cc b/src/ast/loop_statement_test.cc
index cc06c76..6d8521a 100644
--- a/src/ast/loop_statement_test.cc
+++ b/src/ast/loop_statement_test.cc
@@ -27,15 +27,15 @@
 
 TEST_F(LoopStatementTest, Creation) {
   auto* body = Block(create<DiscardStatement>());
-  auto* b = body->last();
+  auto* b = body->Last();
 
   auto* continuing = Block(create<DiscardStatement>());
 
   auto* l = create<LoopStatement>(body, continuing);
-  ASSERT_EQ(l->body()->size(), 1u);
-  EXPECT_EQ(l->body()->get(0), b);
-  ASSERT_EQ(l->continuing()->size(), 1u);
-  EXPECT_EQ(l->continuing()->get(0), continuing->last());
+  ASSERT_EQ(l->body->statements.size(), 1u);
+  EXPECT_EQ(l->body->statements[0], b);
+  ASSERT_EQ(l->continuing->statements.size(), 1u);
+  EXPECT_EQ(l->continuing->statements[0], continuing->Last());
 }
 
 TEST_F(LoopStatementTest, Creation_WithSource) {
@@ -45,7 +45,7 @@
 
   auto* l =
       create<LoopStatement>(Source{Source::Location{20, 2}}, body, continuing);
-  auto src = l->source();
+  auto src = l->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
@@ -59,7 +59,7 @@
   auto* body = Block(create<DiscardStatement>());
 
   auto* l = create<LoopStatement>(body, nullptr);
-  EXPECT_FALSE(l->has_continuing());
+  EXPECT_FALSE(l->continuing);
 }
 
 TEST_F(LoopStatementTest, HasContinuing_WithContinuing) {
@@ -68,7 +68,7 @@
   auto* continuing = Block(create<DiscardStatement>());
 
   auto* l = create<LoopStatement>(body, continuing);
-  EXPECT_TRUE(l->has_continuing());
+  EXPECT_TRUE(l->continuing);
 }
 
 TEST_F(LoopStatementTest, Assert_Null_Body) {
diff --git a/src/ast/matrix.cc b/src/ast/matrix.cc
index 357fe52..2a5801a 100644
--- a/src/ast/matrix.cc
+++ b/src/ast/matrix.cc
@@ -21,15 +21,12 @@
 namespace tint {
 namespace ast {
 
-Matrix::Matrix(ProgramID program_id,
-               const Source& source,
+Matrix::Matrix(ProgramID pid,
+               const Source& src,
                Type* subtype,
-               uint32_t rows,
-               uint32_t columns)
-    : Base(program_id, source),
-      subtype_(subtype),
-      rows_(rows),
-      columns_(columns) {
+               uint32_t r,
+               uint32_t c)
+    : Base(pid, src), type(subtype), rows(r), columns(c) {
   TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, subtype, program_id);
   TINT_ASSERT(AST, rows > 1);
   TINT_ASSERT(AST, rows < 5);
@@ -43,16 +40,16 @@
 
 std::string Matrix::FriendlyName(const SymbolTable& symbols) const {
   std::ostringstream out;
-  out << "mat" << columns_ << "x" << rows_ << "<"
-      << subtype_->FriendlyName(symbols) << ">";
+  out << "mat" << columns << "x" << rows << "<" << type->FriendlyName(symbols)
+      << ">";
   return out.str();
 }
 
 Matrix* Matrix::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* ty = ctx->Clone(type());
-  return ctx->dst->create<Matrix>(src, ty, rows_, columns_);
+  auto src = ctx->Clone(source);
+  auto* ty = ctx->Clone(type);
+  return ctx->dst->create<Matrix>(src, ty, rows, columns);
 }
 
 }  // namespace ast
diff --git a/src/ast/matrix.h b/src/ast/matrix.h
index 27417c2..434ee3f 100644
--- a/src/ast/matrix.h
+++ b/src/ast/matrix.h
@@ -26,13 +26,13 @@
 class Matrix : public Castable<Matrix, Type> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param subtype type matrix type
   /// @param rows the number of rows in the matrix
   /// @param columns the number of columns in the matrix
-  Matrix(ProgramID program_id,
-         const Source& source,
+  Matrix(ProgramID pid,
+         const Source& src,
          Type* subtype,
          uint32_t rows,
          uint32_t columns);
@@ -40,13 +40,6 @@
   Matrix(Matrix&&);
   ~Matrix() override;
 
-  /// @returns the type of the matrix
-  Type* type() const { return subtype_; }
-  /// @returns the number of rows in the matrix
-  uint32_t rows() const { return rows_; }
-  /// @returns the number of columns in the matrix
-  uint32_t columns() const { return columns_; }
-
   /// @param symbols the program's symbol table
   /// @returns the name for this type that closely resembles how it would be
   /// declared in WGSL.
@@ -57,10 +50,14 @@
   /// @return the newly cloned type
   Matrix* Clone(CloneContext* ctx) const override;
 
- private:
-  Type* const subtype_;
-  uint32_t const rows_;
-  uint32_t const columns_;
+  /// The type of the matrix
+  Type* const type;
+
+  /// The number of rows in the matrix
+  uint32_t const rows;
+
+  /// The number of columns in the matrix
+  uint32_t const columns;
 };
 
 }  // namespace ast
diff --git a/src/ast/matrix_test.cc b/src/ast/matrix_test.cc
index 4e1ed2c..f85ac60 100644
--- a/src/ast/matrix_test.cc
+++ b/src/ast/matrix_test.cc
@@ -36,9 +36,9 @@
 TEST_F(AstMatrixTest, Creation) {
   auto* i32 = create<I32>();
   auto* m = create<Matrix>(i32, 2, 4);
-  EXPECT_EQ(m->type(), i32);
-  EXPECT_EQ(m->rows(), 2u);
-  EXPECT_EQ(m->columns(), 4u);
+  EXPECT_EQ(m->type, i32);
+  EXPECT_EQ(m->rows, 2u);
+  EXPECT_EQ(m->columns, 4u);
 }
 
 TEST_F(AstMatrixTest, FriendlyName) {
diff --git a/src/ast/member_accessor_expression.cc b/src/ast/member_accessor_expression.cc
index 7e75488..4dc3bf8 100644
--- a/src/ast/member_accessor_expression.cc
+++ b/src/ast/member_accessor_expression.cc
@@ -21,15 +21,15 @@
 namespace tint {
 namespace ast {
 
-MemberAccessorExpression::MemberAccessorExpression(ProgramID program_id,
-                                                   const Source& source,
-                                                   Expression* structure,
-                                                   IdentifierExpression* member)
-    : Base(program_id, source), struct_(structure), member_(member) {
-  TINT_ASSERT(AST, struct_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, struct_, program_id);
-  TINT_ASSERT(AST, member_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, member_, program_id);
+MemberAccessorExpression::MemberAccessorExpression(ProgramID pid,
+                                                   const Source& src,
+                                                   Expression* str,
+                                                   IdentifierExpression* mem)
+    : Base(pid, src), structure(str), member(mem) {
+  TINT_ASSERT(AST, structure);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, structure, program_id);
+  TINT_ASSERT(AST, member);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, member, program_id);
 }
 
 MemberAccessorExpression::MemberAccessorExpression(MemberAccessorExpression&&) =
@@ -40,9 +40,9 @@
 MemberAccessorExpression* MemberAccessorExpression::Clone(
     CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* str = ctx->Clone(structure());
-  auto* mem = ctx->Clone(member());
+  auto src = ctx->Clone(source);
+  auto* str = ctx->Clone(structure);
+  auto* mem = ctx->Clone(member);
   return ctx->dst->create<MemberAccessorExpression>(src, str, mem);
 }
 
diff --git a/src/ast/member_accessor_expression.h b/src/ast/member_accessor_expression.h
index 46ddd5d..a5c0bed 100644
--- a/src/ast/member_accessor_expression.h
+++ b/src/ast/member_accessor_expression.h
@@ -37,22 +37,20 @@
   MemberAccessorExpression(MemberAccessorExpression&&);
   ~MemberAccessorExpression() override;
 
-  /// @returns the structure
-  Expression* structure() const { return struct_; }
-  /// @returns the member expression
-  IdentifierExpression* member() const { return member_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   MemberAccessorExpression* Clone(CloneContext* ctx) const override;
 
+  /// The structure
+  Expression* const structure;
+
+  /// The member expression
+  IdentifierExpression* const member;
+
  private:
   MemberAccessorExpression(const MemberAccessorExpression&) = delete;
-
-  Expression* const struct_;
-  IdentifierExpression* const member_;
 };
 
 }  // namespace ast
diff --git a/src/ast/member_accessor_expression_test.cc b/src/ast/member_accessor_expression_test.cc
index 66179ce..8b33624 100644
--- a/src/ast/member_accessor_expression_test.cc
+++ b/src/ast/member_accessor_expression_test.cc
@@ -26,14 +26,14 @@
   auto* mem = Expr("member");
 
   auto* stmt = create<MemberAccessorExpression>(str, mem);
-  EXPECT_EQ(stmt->structure(), str);
-  EXPECT_EQ(stmt->member(), mem);
+  EXPECT_EQ(stmt->structure, str);
+  EXPECT_EQ(stmt->member, mem);
 }
 
 TEST_F(MemberAccessorExpressionTest, Creation_WithSource) {
   auto* stmt = create<MemberAccessorExpression>(
       Source{Source::Location{20, 2}}, Expr("structure"), Expr("member"));
-  auto src = stmt->source();
+  auto src = stmt->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/module.cc b/src/ast/module.cc
index 029af15..33ccd05 100644
--- a/src/ast/module.cc
+++ b/src/ast/module.cc
@@ -24,13 +24,12 @@
 namespace tint {
 namespace ast {
 
-Module::Module(ProgramID program_id, const Source& source)
-    : Base(program_id, source) {}
+Module::Module(ProgramID pid, const Source& src) : Base(pid, src) {}
 
-Module::Module(ProgramID program_id,
-               const Source& source,
+Module::Module(ProgramID pid,
+               const Source& src,
                std::vector<ast::Node*> global_decls)
-    : Base(program_id, source), global_declarations_(std::move(global_decls)) {
+    : Base(pid, src), global_declarations_(std::move(global_decls)) {
   for (auto* decl : global_declarations_) {
     if (decl == nullptr) {
       continue;
@@ -53,7 +52,7 @@
 
 const ast::TypeDecl* Module::LookupType(Symbol name) const {
   for (auto* ty : TypeDecls()) {
-    if (ty->name() == name) {
+    if (ty->name == name) {
       return ty;
     }
   }
@@ -62,21 +61,21 @@
 
 void Module::AddGlobalVariable(ast::Variable* var) {
   TINT_ASSERT(AST, var);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id());
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id);
   global_variables_.push_back(var);
   global_declarations_.push_back(var);
 }
 
 void Module::AddTypeDecl(ast::TypeDecl* type) {
   TINT_ASSERT(AST, type);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id());
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
   type_decls_.push_back(type);
   global_declarations_.push_back(type);
 }
 
 void Module::AddFunction(ast::Function* func) {
   TINT_ASSERT(AST, func);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id());
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id);
   functions_.push_back(func);
   global_declarations_.push_back(func);
 }
@@ -103,13 +102,13 @@
       continue;
     }
     if (auto* type = decl->As<ast::TypeDecl>()) {
-      TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id());
+      TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, type, program_id);
       type_decls_.push_back(type);
     } else if (auto* func = decl->As<Function>()) {
-      TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id());
+      TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, func, program_id);
       functions_.push_back(func);
     } else if (auto* var = decl->As<Variable>()) {
-      TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id());
+      TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, var, program_id);
       global_variables_.push_back(var);
     } else {
       TINT_ICE(AST, ctx->dst->Diagnostics())
diff --git a/src/ast/module.h b/src/ast/module.h
index ab52095..a4e392c 100644
--- a/src/ast/module.h
+++ b/src/ast/module.h
@@ -31,17 +31,17 @@
 class Module : public Castable<Module, Node> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of the module
-  Module(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  Module(ProgramID pid, const Source& src);
 
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of the module
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param global_decls the list of global types, functions, and variables, in
   /// the order they were declared in the source program
-  Module(ProgramID program_id,
-         const Source& source,
+  Module(ProgramID pid,
+         const Source& src,
          std::vector<ast::Node*> global_decls);
 
   /// Destructor
diff --git a/src/ast/module_test.cc b/src/ast/module_test.cc
index 861c4d0..e36a2b8 100644
--- a/src/ast/module_test.cc
+++ b/src/ast/module_test.cc
@@ -130,11 +130,11 @@
   ASSERT_TRUE(decls[2]->Is<ast::Alias>());
   ASSERT_TRUE(decls[4]->Is<ast::Alias>());
 
-  ASSERT_EQ(cloned.Symbols().NameFor(decls[0]->As<ast::Alias>()->name()),
+  ASSERT_EQ(cloned.Symbols().NameFor(decls[0]->As<ast::Alias>()->name),
             "inserted_before_F");
-  ASSERT_EQ(cloned.Symbols().NameFor(decls[2]->As<ast::Alias>()->name()),
+  ASSERT_EQ(cloned.Symbols().NameFor(decls[2]->As<ast::Alias>()->name),
             "inserted_before_A");
-  ASSERT_EQ(cloned.Symbols().NameFor(decls[4]->As<ast::Alias>()->name()),
+  ASSERT_EQ(cloned.Symbols().NameFor(decls[4]->As<ast::Alias>()->name),
             "inserted_before_V");
 }
 
diff --git a/src/ast/multisampled_texture.cc b/src/ast/multisampled_texture.cc
index a5328f9..bd8127e 100644
--- a/src/ast/multisampled_texture.cc
+++ b/src/ast/multisampled_texture.cc
@@ -21,12 +21,12 @@
 namespace tint {
 namespace ast {
 
-MultisampledTexture::MultisampledTexture(ProgramID program_id,
-                                         const Source& source,
-                                         TextureDimension dim,
-                                         Type* type)
-    : Base(program_id, source, dim), type_(type) {
-  TINT_ASSERT(AST, type_);
+MultisampledTexture::MultisampledTexture(ProgramID pid,
+                                         const Source& src,
+                                         TextureDimension d,
+                                         Type* ty)
+    : Base(pid, src, d), type(ty) {
+  TINT_ASSERT(AST, type);
 }
 
 MultisampledTexture::MultisampledTexture(MultisampledTexture&&) = default;
@@ -36,16 +36,16 @@
 std::string MultisampledTexture::FriendlyName(
     const SymbolTable& symbols) const {
   std::ostringstream out;
-  out << "texture_multisampled_" << dim() << "<" << type_->FriendlyName(symbols)
+  out << "texture_multisampled_" << dim << "<" << type->FriendlyName(symbols)
       << ">";
   return out.str();
 }
 
 MultisampledTexture* MultisampledTexture::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* ty = ctx->Clone(type());
-  return ctx->dst->create<MultisampledTexture>(src, dim(), ty);
+  auto src = ctx->Clone(source);
+  auto* ty = ctx->Clone(type);
+  return ctx->dst->create<MultisampledTexture>(src, dim, ty);
 }
 
 }  // namespace ast
diff --git a/src/ast/multisampled_texture.h b/src/ast/multisampled_texture.h
index 0c44a91..c1cef57 100644
--- a/src/ast/multisampled_texture.h
+++ b/src/ast/multisampled_texture.h
@@ -26,21 +26,18 @@
 class MultisampledTexture : public Castable<MultisampledTexture, Texture> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param dim the dimensionality of the texture
   /// @param type the data type of the multisampled texture
-  MultisampledTexture(ProgramID program_id,
-                      const Source& source,
+  MultisampledTexture(ProgramID pid,
+                      const Source& src,
                       TextureDimension dim,
                       Type* type);
   /// Move constructor
   MultisampledTexture(MultisampledTexture&&);
   ~MultisampledTexture() override;
 
-  /// @returns the subtype of the sampled texture
-  Type* type() const { return type_; }
-
   /// @param symbols the program's symbol table
   /// @returns the name for this type that closely resembles how it would be
   /// declared in WGSL.
@@ -51,8 +48,8 @@
   /// @return the newly cloned type
   MultisampledTexture* Clone(CloneContext* ctx) const override;
 
- private:
-  Type* const type_;
+  /// The subtype of the multisampled texture
+  Type* const type;
 };
 
 }  // namespace ast
diff --git a/src/ast/multisampled_texture_test.cc b/src/ast/multisampled_texture_test.cc
index 4067749..699d76b 100644
--- a/src/ast/multisampled_texture_test.cc
+++ b/src/ast/multisampled_texture_test.cc
@@ -50,13 +50,13 @@
 TEST_F(AstMultisampledTextureTest, Dim) {
   auto* f32 = create<F32>();
   auto* s = create<MultisampledTexture>(TextureDimension::k3d, f32);
-  EXPECT_EQ(s->dim(), TextureDimension::k3d);
+  EXPECT_EQ(s->dim, TextureDimension::k3d);
 }
 
 TEST_F(AstMultisampledTextureTest, Type) {
   auto* f32 = create<F32>();
   auto* s = create<MultisampledTexture>(TextureDimension::k3d, f32);
-  EXPECT_EQ(s->type(), f32);
+  EXPECT_EQ(s->type, f32);
 }
 
 TEST_F(AstMultisampledTextureTest, FriendlyName) {
diff --git a/src/ast/node.cc b/src/ast/node.cc
index c4c7591..92ac290 100644
--- a/src/ast/node.cc
+++ b/src/ast/node.cc
@@ -19,17 +19,11 @@
 namespace tint {
 namespace ast {
 
-Node::Node(ProgramID program_id, const Source& source)
-    : program_id_(program_id), source_(source) {}
+Node::Node(ProgramID pid, const Source& src) : program_id(pid), source(src) {}
 
 Node::Node(Node&&) = default;
 
 Node::~Node() = default;
 
-void Node::make_indent(std::ostream& out, size_t indent) const {
-  for (size_t i = 0; i < indent; ++i)
-    out << " ";
-}
-
 }  // namespace ast
 }  // namespace tint
diff --git a/src/ast/node.h b/src/ast/node.h
index 10546b0..242f7a3 100644
--- a/src/ast/node.h
+++ b/src/ast/node.h
@@ -37,30 +37,22 @@
  public:
   ~Node() override;
 
-  /// @returns the identifier of the program that owns this node
-  ProgramID program_id() const { return program_id_; }
+  /// The identifier of the program that owns this node
+  ProgramID const program_id;
 
-  /// @returns the node source data
-  const Source& source() const { return source_; }
+  /// The node source data
+  Source const source;
 
  protected:
   /// Create a new node
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the input source for the node
-  Node(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the input source for the node
+  Node(ProgramID pid, const Source& src);
   /// Move constructor
   Node(Node&&);
 
-  /// Writes indent into stream
-  /// @param out the stream to write to
-  /// @param indent the number of spaces to write
-  void make_indent(std::ostream& out, size_t indent) const;
-
  private:
   Node(const Node&) = delete;
-
-  ProgramID const program_id_;
-  Source const source_;
 };
 
 }  // namespace ast
@@ -68,7 +60,7 @@
 /// @param node a pointer to an AST node
 /// @returns the ProgramID of the given AST node.
 inline ProgramID ProgramIDOf(const ast::Node* node) {
-  return node ? node->program_id() : ProgramID();
+  return node ? node->program_id : ProgramID();
 }
 
 }  // namespace tint
diff --git a/src/ast/override_decoration.cc b/src/ast/override_decoration.cc
index 312c7fd..6227d9c 100644
--- a/src/ast/override_decoration.cc
+++ b/src/ast/override_decoration.cc
@@ -23,26 +23,25 @@
 namespace tint {
 namespace ast {
 
-OverrideDecoration::OverrideDecoration(ProgramID program_id,
-                                       const Source& source)
-    : Base(program_id, source), has_value_(false), value_(0) {}
+OverrideDecoration::OverrideDecoration(ProgramID pid, const Source& src)
+    : Base(pid, src), has_value(false), value(0) {}
 
-OverrideDecoration::OverrideDecoration(ProgramID program_id,
-                                       const Source& source,
+OverrideDecoration::OverrideDecoration(ProgramID pid,
+                                       const Source& src,
                                        uint32_t val)
-    : Base(program_id, source), has_value_(true), value_(val) {}
+    : Base(pid, src), has_value(true), value(val) {}
 
 OverrideDecoration::~OverrideDecoration() = default;
 
-std::string OverrideDecoration::name() const {
+std::string OverrideDecoration::Name() const {
   return "override";
 }
 
 OverrideDecoration* OverrideDecoration::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  if (has_value_) {
-    return ctx->dst->create<OverrideDecoration>(src, value_);
+  auto src = ctx->Clone(source);
+  if (has_value) {
+    return ctx->dst->create<OverrideDecoration>(src, value);
   } else {
     return ctx->dst->create<OverrideDecoration>(src);
   }
diff --git a/src/ast/override_decoration.h b/src/ast/override_decoration.h
index 09e251f..714498a 100644
--- a/src/ast/override_decoration.h
+++ b/src/ast/override_decoration.h
@@ -26,24 +26,18 @@
 class OverrideDecoration : public Castable<OverrideDecoration, Decoration> {
  public:
   /// Create an override decoration with no specified id.
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this decoration
-  OverrideDecoration(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  OverrideDecoration(ProgramID pid, const Source& src);
   /// Create an override decoration with a specific id value.
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this decoration
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param val the override value
-  OverrideDecoration(ProgramID program_id, const Source& source, uint32_t val);
+  OverrideDecoration(ProgramID pid, const Source& src, uint32_t val);
   ~OverrideDecoration() override;
 
-  /// @returns true if an override id was specified
-  uint32_t HasValue() const { return has_value_; }
-
-  /// @returns the override id value
-  uint32_t value() const { return value_; }
-
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -51,9 +45,11 @@
   /// @return the newly cloned node
   OverrideDecoration* Clone(CloneContext* ctx) const override;
 
- private:
-  bool has_value_;
-  uint32_t const value_;
+  /// True if an override id was specified
+  bool const has_value;
+
+  /// The override id value
+  uint32_t const value;
 };
 
 }  // namespace ast
diff --git a/src/ast/override_decoration_test.cc b/src/ast/override_decoration_test.cc
index fc655b2..34a25ed 100644
--- a/src/ast/override_decoration_test.cc
+++ b/src/ast/override_decoration_test.cc
@@ -24,13 +24,13 @@
 
 TEST_F(OverrideDecorationTest, Creation_WithValue) {
   auto* d = create<OverrideDecoration>(12);
-  EXPECT_TRUE(d->HasValue());
-  EXPECT_EQ(12u, d->value());
+  EXPECT_TRUE(d->has_value);
+  EXPECT_EQ(12u, d->value);
 }
 
 TEST_F(OverrideDecorationTest, Creation_WithoutValue) {
   auto* d = create<OverrideDecoration>();
-  EXPECT_FALSE(d->HasValue());
+  EXPECT_FALSE(d->has_value);
 }
 
 }  // namespace
diff --git a/src/ast/pointer.cc b/src/ast/pointer.cc
index 2c97ae4..4ae782d 100644
--- a/src/ast/pointer.cc
+++ b/src/ast/pointer.cc
@@ -21,25 +21,22 @@
 namespace tint {
 namespace ast {
 
-Pointer::Pointer(ProgramID program_id,
-                 const Source& source,
+Pointer::Pointer(ProgramID pid,
+                 const Source& src,
                  Type* const subtype,
-                 ast::StorageClass storage_class,
-                 ast::Access access)
-    : Base(program_id, source),
-      subtype_(subtype),
-      storage_class_(storage_class),
-      access_(access) {}
+                 ast::StorageClass sc,
+                 ast::Access ac)
+    : Base(pid, src), type(subtype), storage_class(sc), access(ac) {}
 
 std::string Pointer::FriendlyName(const SymbolTable& symbols) const {
   std::ostringstream out;
   out << "ptr<";
-  if (storage_class_ != ast::StorageClass::kNone) {
-    out << storage_class_ << ", ";
+  if (storage_class != ast::StorageClass::kNone) {
+    out << storage_class << ", ";
   }
-  out << subtype_->FriendlyName(symbols);
-  if (access_ != ast::Access::kUndefined) {
-    out << ", " << access_;
+  out << type->FriendlyName(symbols);
+  if (access != ast::Access::kUndefined) {
+    out << ", " << access;
   }
   out << ">";
   return out.str();
@@ -51,9 +48,9 @@
 
 Pointer* Pointer::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* ty = ctx->Clone(type());
-  return ctx->dst->create<Pointer>(src, ty, storage_class_, access_);
+  auto src = ctx->Clone(source);
+  auto* ty = ctx->Clone(type);
+  return ctx->dst->create<Pointer>(src, ty, storage_class, access);
 }
 
 }  // namespace ast
diff --git a/src/ast/pointer.h b/src/ast/pointer.h
index 2469d65..b621c95 100644
--- a/src/ast/pointer.h
+++ b/src/ast/pointer.h
@@ -28,13 +28,13 @@
 class Pointer : public Castable<Pointer, Type> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param subtype the pointee type
   /// @param storage_class the storage class of the pointer
   /// @param access the access control of the pointer
-  Pointer(ProgramID program_id,
-          const Source& source,
+  Pointer(ProgramID pid,
+          const Source& src,
           Type* const subtype,
           ast::StorageClass storage_class,
           ast::Access access);
@@ -42,15 +42,6 @@
   Pointer(Pointer&&);
   ~Pointer() override;
 
-  /// @returns the pointee type
-  Type* type() const { return const_cast<Type*>(subtype_); }
-
-  /// @returns the storage class of the pointer
-  ast::StorageClass storage_class() const { return storage_class_; }
-
-  /// @returns the access control of the pointer
-  ast::Access access() const { return access_; }
-
   /// @param symbols the program's symbol table
   /// @returns the name for this type that closely resembles how it would be
   /// declared in WGSL.
@@ -61,10 +52,14 @@
   /// @return the newly cloned type
   Pointer* Clone(CloneContext* ctx) const override;
 
- private:
-  Type const* const subtype_;
-  ast::StorageClass const storage_class_;
-  ast::Access const access_;
+  /// The pointee type
+  Type* const type;
+
+  /// The storage class of the pointer
+  ast::StorageClass const storage_class;
+
+  /// The access control of the pointer
+  ast::Access const access;
 };
 
 }  // namespace ast
diff --git a/src/ast/pointer_test.cc b/src/ast/pointer_test.cc
index 9e18782..a8dff94 100644
--- a/src/ast/pointer_test.cc
+++ b/src/ast/pointer_test.cc
@@ -26,9 +26,9 @@
 TEST_F(AstPointerTest, Creation) {
   auto* i32 = create<I32>();
   auto* p = create<Pointer>(i32, ast::StorageClass::kStorage, Access::kRead);
-  EXPECT_EQ(p->type(), i32);
-  EXPECT_EQ(p->storage_class(), ast::StorageClass::kStorage);
-  EXPECT_EQ(p->access(), Access::kRead);
+  EXPECT_EQ(p->type, i32);
+  EXPECT_EQ(p->storage_class, ast::StorageClass::kStorage);
+  EXPECT_EQ(p->access, Access::kRead);
 }
 
 TEST_F(AstPointerTest, FriendlyName) {
diff --git a/src/ast/return_statement.cc b/src/ast/return_statement.cc
index 5888470..e48be37 100644
--- a/src/ast/return_statement.cc
+++ b/src/ast/return_statement.cc
@@ -21,14 +21,14 @@
 namespace tint {
 namespace ast {
 
-ReturnStatement::ReturnStatement(ProgramID program_id, const Source& source)
-    : Base(program_id, source), value_(nullptr) {}
+ReturnStatement::ReturnStatement(ProgramID pid, const Source& src)
+    : Base(pid, src), value(nullptr) {}
 
-ReturnStatement::ReturnStatement(ProgramID program_id,
-                                 const Source& source,
-                                 Expression* value)
-    : Base(program_id, source), value_(value) {
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, value_, program_id);
+ReturnStatement::ReturnStatement(ProgramID pid,
+                                 const Source& src,
+                                 Expression* val)
+    : Base(pid, src), value(val) {
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, value, program_id);
 }
 
 ReturnStatement::ReturnStatement(ReturnStatement&&) = default;
@@ -37,8 +37,8 @@
 
 ReturnStatement* ReturnStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* ret = ctx->Clone(value());
+  auto src = ctx->Clone(source);
+  auto* ret = ctx->Clone(value);
   return ctx->dst->create<ReturnStatement>(src, ret);
 }
 
diff --git a/src/ast/return_statement.h b/src/ast/return_statement.h
index c8420f8..c6dd4a6 100644
--- a/src/ast/return_statement.h
+++ b/src/ast/return_statement.h
@@ -25,36 +25,30 @@
 class ReturnStatement : public Castable<ReturnStatement, Statement> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source information
-  ReturnStatement(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  ReturnStatement(ProgramID pid, const Source& src);
 
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the return statement source
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param value the return value
-  ReturnStatement(ProgramID program_id,
-                  const Source& source,
-                  Expression* value);
+  ReturnStatement(ProgramID pid, const Source& src, Expression* value);
   /// Move constructor
   ReturnStatement(ReturnStatement&&);
   ~ReturnStatement() override;
 
-  /// @returns the value
-  Expression* value() const { return value_; }
-  /// @returns true if the return has a value
-  bool has_value() const { return value_ != nullptr; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   ReturnStatement* Clone(CloneContext* ctx) const override;
 
+  /// The value returned. May be null.
+  Expression* const value;
+
  private:
   ReturnStatement(const ReturnStatement&) = delete;
-
-  Expression* const value_;
 };
 
 }  // namespace ast
diff --git a/src/ast/return_statement_test.cc b/src/ast/return_statement_test.cc
index dbc5c11..3d2403a 100644
--- a/src/ast/return_statement_test.cc
+++ b/src/ast/return_statement_test.cc
@@ -27,12 +27,12 @@
   auto* expr = Expr("expr");
 
   auto* r = create<ReturnStatement>(expr);
-  EXPECT_EQ(r->value(), expr);
+  EXPECT_EQ(r->value, expr);
 }
 
 TEST_F(ReturnStatementTest, Creation_WithSource) {
   auto* r = create<ReturnStatement>(Source{Source::Location{20, 2}});
-  auto src = r->source();
+  auto src = r->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
@@ -42,15 +42,15 @@
   EXPECT_TRUE(r->Is<ReturnStatement>());
 }
 
-TEST_F(ReturnStatementTest, HasValue_WithoutValue) {
+TEST_F(ReturnStatementTest, WithoutValue) {
   auto* r = create<ReturnStatement>();
-  EXPECT_FALSE(r->has_value());
+  EXPECT_EQ(r->value, nullptr);
 }
 
-TEST_F(ReturnStatementTest, HasValue_WithValue) {
+TEST_F(ReturnStatementTest, WithValue) {
   auto* expr = Expr("expr");
   auto* r = create<ReturnStatement>(expr);
-  EXPECT_TRUE(r->has_value());
+  EXPECT_NE(r->value, nullptr);
 }
 
 TEST_F(ReturnStatementTest, Assert_DifferentProgramID_Expr) {
diff --git a/src/ast/sampled_texture.cc b/src/ast/sampled_texture.cc
index cc1109f..11e0d17 100644
--- a/src/ast/sampled_texture.cc
+++ b/src/ast/sampled_texture.cc
@@ -21,12 +21,12 @@
 namespace tint {
 namespace ast {
 
-SampledTexture::SampledTexture(ProgramID program_id,
-                               const Source& source,
-                               TextureDimension dim,
-                               Type const* type)
-    : Base(program_id, source, dim), type_(type) {
-  TINT_ASSERT(AST, type_);
+SampledTexture::SampledTexture(ProgramID pid,
+                               const Source& src,
+                               TextureDimension d,
+                               Type const* ty)
+    : Base(pid, src, d), type(const_cast<Type*>(ty)) {
+  TINT_ASSERT(AST, type);
 }
 
 SampledTexture::SampledTexture(SampledTexture&&) = default;
@@ -35,15 +35,15 @@
 
 std::string SampledTexture::FriendlyName(const SymbolTable& symbols) const {
   std::ostringstream out;
-  out << "texture_" << dim() << "<" << type_->FriendlyName(symbols) << ">";
+  out << "texture_" << dim << "<" << type->FriendlyName(symbols) << ">";
   return out.str();
 }
 
 SampledTexture* SampledTexture::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* ty = ctx->Clone(type());
-  return ctx->dst->create<SampledTexture>(src, dim(), ty);
+  auto src = ctx->Clone(source);
+  auto* ty = ctx->Clone(type);
+  return ctx->dst->create<SampledTexture>(src, dim, ty);
 }
 
 }  // namespace ast
diff --git a/src/ast/sampled_texture.h b/src/ast/sampled_texture.h
index 9bfc52a..0530767 100644
--- a/src/ast/sampled_texture.h
+++ b/src/ast/sampled_texture.h
@@ -26,21 +26,18 @@
 class SampledTexture : public Castable<SampledTexture, Texture> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param dim the dimensionality of the texture
   /// @param type the data type of the sampled texture
-  SampledTexture(ProgramID program_id,
-                 const Source& source,
+  SampledTexture(ProgramID pid,
+                 const Source& src,
                  TextureDimension dim,
                  Type const* type);
   /// Move constructor
   SampledTexture(SampledTexture&&);
   ~SampledTexture() override;
 
-  /// @returns the subtype of the sampled texture
-  Type* type() const { return const_cast<Type*>(type_); }
-
   /// @param symbols the program's symbol table
   /// @returns the name for this type that closely resembles how it would be
   /// declared in WGSL.
@@ -51,8 +48,8 @@
   /// @return the newly cloned type
   SampledTexture* Clone(CloneContext* ctx) const override;
 
- private:
-  Type const* const type_;
+  /// The subtype of the sampled texture
+  Type* const type;
 };
 
 }  // namespace ast
diff --git a/src/ast/sampled_texture_test.cc b/src/ast/sampled_texture_test.cc
index 12f1b8f..74ade1e 100644
--- a/src/ast/sampled_texture_test.cc
+++ b/src/ast/sampled_texture_test.cc
@@ -34,13 +34,13 @@
 TEST_F(AstSampledTextureTest, Dim) {
   auto* f32 = create<F32>();
   auto* s = create<SampledTexture>(TextureDimension::k3d, f32);
-  EXPECT_EQ(s->dim(), TextureDimension::k3d);
+  EXPECT_EQ(s->dim, TextureDimension::k3d);
 }
 
 TEST_F(AstSampledTextureTest, Type) {
   auto* f32 = create<F32>();
   auto* s = create<SampledTexture>(TextureDimension::k3d, f32);
-  EXPECT_EQ(s->type(), f32);
+  EXPECT_EQ(s->type, f32);
 }
 
 TEST_F(AstSampledTextureTest, FriendlyName) {
diff --git a/src/ast/sampler.cc b/src/ast/sampler.cc
index 5a6ca23..e2387bb 100644
--- a/src/ast/sampler.cc
+++ b/src/ast/sampler.cc
@@ -33,20 +33,20 @@
   return out;
 }
 
-Sampler::Sampler(ProgramID program_id, const Source& source, SamplerKind kind)
-    : Base(program_id, source), kind_(kind) {}
+Sampler::Sampler(ProgramID pid, const Source& src, SamplerKind k)
+    : Base(pid, src), kind(k) {}
 
 Sampler::Sampler(Sampler&&) = default;
 
 Sampler::~Sampler() = default;
 
 std::string Sampler::FriendlyName(const SymbolTable&) const {
-  return kind_ == SamplerKind::kSampler ? "sampler" : "sampler_comparison";
+  return kind == SamplerKind::kSampler ? "sampler" : "sampler_comparison";
 }
 
 Sampler* Sampler::Clone(CloneContext* ctx) const {
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<Sampler>(src, kind_);
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<Sampler>(src, kind);
 }
 
 }  // namespace ast
diff --git a/src/ast/sampler.h b/src/ast/sampler.h
index 797a4f2..64bf4ea 100644
--- a/src/ast/sampler.h
+++ b/src/ast/sampler.h
@@ -39,19 +39,16 @@
 class Sampler : public Castable<Sampler, Type> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param kind the kind of sampler
-  Sampler(ProgramID program_id, const Source& source, SamplerKind kind);
+  Sampler(ProgramID pid, const Source& src, SamplerKind kind);
   /// Move constructor
   Sampler(Sampler&&);
   ~Sampler() override;
 
-  /// @returns the sampler type
-  SamplerKind kind() const { return kind_; }
-
   /// @returns true if this is a comparison sampler
-  bool IsComparison() const { return kind_ == SamplerKind::kComparisonSampler; }
+  bool IsComparison() const { return kind == SamplerKind::kComparisonSampler; }
 
   /// @param symbols the program's symbol table
   /// @returns the name for this type that closely resembles how it would be
@@ -63,8 +60,8 @@
   /// @return the newly cloned type
   Sampler* Clone(CloneContext* ctx) const override;
 
- private:
-  SamplerKind const kind_;
+  /// The sampler type
+  SamplerKind const kind;
 };
 
 }  // namespace ast
diff --git a/src/ast/sampler_test.cc b/src/ast/sampler_test.cc
index 2f9c202..12de46e 100644
--- a/src/ast/sampler_test.cc
+++ b/src/ast/sampler_test.cc
@@ -24,12 +24,12 @@
 
 TEST_F(AstSamplerTest, Creation) {
   auto* s = create<Sampler>(SamplerKind::kSampler);
-  EXPECT_EQ(s->kind(), SamplerKind::kSampler);
+  EXPECT_EQ(s->kind, SamplerKind::kSampler);
 }
 
 TEST_F(AstSamplerTest, Creation_ComparisonSampler) {
   auto* s = create<Sampler>(SamplerKind::kComparisonSampler);
-  EXPECT_EQ(s->kind(), SamplerKind::kComparisonSampler);
+  EXPECT_EQ(s->kind, SamplerKind::kComparisonSampler);
   EXPECT_TRUE(s->IsComparison());
 }
 
diff --git a/src/ast/scalar_constructor_expression.cc b/src/ast/scalar_constructor_expression.cc
index 83b9da3..74e6e78 100644
--- a/src/ast/scalar_constructor_expression.cc
+++ b/src/ast/scalar_constructor_expression.cc
@@ -21,10 +21,10 @@
 namespace tint {
 namespace ast {
 
-ScalarConstructorExpression::ScalarConstructorExpression(ProgramID program_id,
-                                                         const Source& source,
-                                                         Literal* literal)
-    : Base(program_id, source), literal_(literal) {
+ScalarConstructorExpression::ScalarConstructorExpression(ProgramID pid,
+                                                         const Source& src,
+                                                         Literal* lit)
+    : Base(pid, src), literal(lit) {
   TINT_ASSERT(AST, literal);
   TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, literal, program_id);
 }
@@ -37,8 +37,8 @@
 ScalarConstructorExpression* ScalarConstructorExpression::Clone(
     CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* lit = ctx->Clone(literal());
+  auto src = ctx->Clone(source);
+  auto* lit = ctx->Clone(literal);
   return ctx->dst->create<ScalarConstructorExpression>(src, lit);
 }
 
diff --git a/src/ast/scalar_constructor_expression.h b/src/ast/scalar_constructor_expression.h
index 0a7925d..ad1d1ca 100644
--- a/src/ast/scalar_constructor_expression.h
+++ b/src/ast/scalar_constructor_expression.h
@@ -26,29 +26,27 @@
     : public Castable<ScalarConstructorExpression, ConstructorExpression> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the constructor source
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param literal the const literal
-  ScalarConstructorExpression(ProgramID program_id,
-                              const Source& source,
+  ScalarConstructorExpression(ProgramID pid,
+                              const Source& src,
                               Literal* literal);
   /// Move constructor
   ScalarConstructorExpression(ScalarConstructorExpression&&);
   ~ScalarConstructorExpression() override;
 
-  /// @returns the literal value
-  Literal* literal() const { return literal_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   ScalarConstructorExpression* Clone(CloneContext* ctx) const override;
 
+  /// The literal value
+  Literal* const literal;
+
  private:
   ScalarConstructorExpression(const ScalarConstructorExpression&) = delete;
-
-  Literal* const literal_;
 };
 
 }  // namespace ast
diff --git a/src/ast/scalar_constructor_expression_test.cc b/src/ast/scalar_constructor_expression_test.cc
index 8548d0d..1c184d5 100644
--- a/src/ast/scalar_constructor_expression_test.cc
+++ b/src/ast/scalar_constructor_expression_test.cc
@@ -24,12 +24,12 @@
 TEST_F(ScalarConstructorExpressionTest, Creation) {
   auto* b = create<BoolLiteral>(true);
   auto* c = create<ScalarConstructorExpression>(b);
-  EXPECT_EQ(c->literal(), b);
+  EXPECT_EQ(c->literal, b);
 }
 
 TEST_F(ScalarConstructorExpressionTest, Creation_WithSource) {
   SetSource(Source{Source::Location{20, 2}});
-  auto src = Expr(true)->source();
+  auto src = Expr(true)->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/sint_literal.cc b/src/ast/sint_literal.cc
index 710ecab..2e6f232 100644
--- a/src/ast/sint_literal.cc
+++ b/src/ast/sint_literal.cc
@@ -21,21 +21,19 @@
 namespace tint {
 namespace ast {
 
-SintLiteral::SintLiteral(ProgramID program_id,
-                         const Source& source,
-                         int32_t value)
-    : Base(program_id, source, static_cast<uint32_t>(value)) {}
+SintLiteral::SintLiteral(ProgramID pid, const Source& src, int32_t val)
+    : Base(pid, src), value(val) {}
 
 SintLiteral::~SintLiteral() = default;
 
-std::string SintLiteral::name() const {
-  return "__sint_" + std::to_string(value());
+uint32_t SintLiteral::ValueAsU32() const {
+  return static_cast<uint32_t>(value);
 }
 
 SintLiteral* SintLiteral::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<SintLiteral>(src, value());
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<SintLiteral>(src, value);
 }
 
 }  // namespace ast
diff --git a/src/ast/sint_literal.h b/src/ast/sint_literal.h
index b0a2baa..75f9aa3 100644
--- a/src/ast/sint_literal.h
+++ b/src/ast/sint_literal.h
@@ -26,23 +26,23 @@
 class SintLiteral : public Castable<SintLiteral, IntLiteral> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the input source
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param value the signed int literals value
-  SintLiteral(ProgramID program_id, const Source& source, int32_t value);
+  SintLiteral(ProgramID pid, const Source& src, int32_t value);
   ~SintLiteral() override;
 
-  /// @returns the int literal value
-  int32_t value() const { return static_cast<int32_t>(value_as_u32()); }
-
-  /// @returns the name for this literal. This name is unique to this value.
-  std::string name() const override;
+  /// @returns the literal value as a u32
+  uint32_t ValueAsU32() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   SintLiteral* Clone(CloneContext* ctx) const override;
+
+  /// The int literal value
+  int32_t const value;
 };
 
 }  // namespace ast
diff --git a/src/ast/sint_literal_test.cc b/src/ast/sint_literal_test.cc
index d9805f3..7503e62 100644
--- a/src/ast/sint_literal_test.cc
+++ b/src/ast/sint_literal_test.cc
@@ -23,12 +23,7 @@
 TEST_F(SintLiteralTest, Value) {
   auto* i = create<SintLiteral>(47);
   ASSERT_TRUE(i->Is<SintLiteral>());
-  EXPECT_EQ(i->value(), 47);
-}
-
-TEST_F(SintLiteralTest, Name_I32) {
-  auto* i = create<SintLiteral>(2);
-  EXPECT_EQ("__sint_2", i->name());
+  EXPECT_EQ(i->value, 47);
 }
 
 }  // namespace
diff --git a/src/ast/stage_decoration.cc b/src/ast/stage_decoration.cc
index af12ba2..3fd66ee 100644
--- a/src/ast/stage_decoration.cc
+++ b/src/ast/stage_decoration.cc
@@ -23,21 +23,21 @@
 namespace tint {
 namespace ast {
 
-StageDecoration::StageDecoration(ProgramID program_id,
-                                 const Source& source,
-                                 PipelineStage stage)
-    : Base(program_id, source), stage_(stage) {}
+StageDecoration::StageDecoration(ProgramID pid,
+                                 const Source& src,
+                                 PipelineStage s)
+    : Base(pid, src), stage(s) {}
 
 StageDecoration::~StageDecoration() = default;
 
-std::string StageDecoration::name() const {
+std::string StageDecoration::Name() const {
   return "stage";
 }
 
 StageDecoration* StageDecoration::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<StageDecoration>(src, stage_);
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<StageDecoration>(src, stage);
 }
 
 }  // namespace ast
diff --git a/src/ast/stage_decoration.h b/src/ast/stage_decoration.h
index d411d7a..acd0359 100644
--- a/src/ast/stage_decoration.h
+++ b/src/ast/stage_decoration.h
@@ -35,11 +35,8 @@
                   PipelineStage stage);
   ~StageDecoration() override;
 
-  /// @returns the stage
-  PipelineStage value() const { return stage_; }
-
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -47,8 +44,8 @@
   /// @return the newly cloned node
   StageDecoration* Clone(CloneContext* ctx) const override;
 
- private:
-  PipelineStage const stage_;
+  /// The pipeline stage
+  PipelineStage const stage;
 };
 
 }  // namespace ast
diff --git a/src/ast/stage_decoration_test.cc b/src/ast/stage_decoration_test.cc
index e6fc5be..6febb85 100644
--- a/src/ast/stage_decoration_test.cc
+++ b/src/ast/stage_decoration_test.cc
@@ -25,7 +25,7 @@
 
 TEST_F(StageDecorationTest, Creation_1param) {
   auto* d = create<StageDecoration>(PipelineStage::kFragment);
-  EXPECT_EQ(d->value(), PipelineStage::kFragment);
+  EXPECT_EQ(d->stage, PipelineStage::kFragment);
 }
 
 }  // namespace
diff --git a/src/ast/statement.cc b/src/ast/statement.cc
index f4618a0..0121d54 100644
--- a/src/ast/statement.cc
+++ b/src/ast/statement.cc
@@ -31,8 +31,7 @@
 namespace tint {
 namespace ast {
 
-Statement::Statement(ProgramID program_id, const Source& source)
-    : Base(program_id, source) {}
+Statement::Statement(ProgramID pid, const Source& src) : Base(pid, src) {}
 
 Statement::Statement(Statement&&) = default;
 
diff --git a/src/ast/statement.h b/src/ast/statement.h
index b371a1e..24e3cd2 100644
--- a/src/ast/statement.h
+++ b/src/ast/statement.h
@@ -32,9 +32,9 @@
 
  protected:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of the expression
-  Statement(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of the expression
+  Statement(ProgramID pid, const Source& src);
   /// Move constructor
   Statement(Statement&&);
 
diff --git a/src/ast/storage_class.cc b/src/ast/storage_class.cc
index 2ec1ca2..ca15be5 100644
--- a/src/ast/storage_class.cc
+++ b/src/ast/storage_class.cc
@@ -17,7 +17,7 @@
 namespace tint {
 namespace ast {
 
-const char* str(StorageClass sc) {
+const char* ToString(StorageClass sc) {
   switch (sc) {
     case StorageClass::kInvalid:
       return "invalid";
@@ -45,7 +45,7 @@
   return "<unknown>";
 }
 std::ostream& operator<<(std::ostream& out, StorageClass sc) {
-  out << str(sc);
+  out << ToString(sc);
   return out;
 }
 
diff --git a/src/ast/storage_class.h b/src/ast/storage_class.h
index 4f263af..ccfeda2 100644
--- a/src/ast/storage_class.h
+++ b/src/ast/storage_class.h
@@ -44,7 +44,7 @@
 
 /// @param sc the StorageClass
 /// @return the name of the given storage class
-const char* str(StorageClass sc);
+const char* ToString(StorageClass sc);
 
 /// @param out the std::ostream to write to
 /// @param sc the StorageClass
diff --git a/src/ast/storage_texture.cc b/src/ast/storage_texture.cc
index 39f5a1e..6c8783f 100644
--- a/src/ast/storage_texture.cc
+++ b/src/ast/storage_texture.cc
@@ -140,16 +140,13 @@
   return out;
 }
 
-StorageTexture::StorageTexture(ProgramID program_id,
-                               const Source& source,
-                               TextureDimension dim,
-                               ImageFormat format,
+StorageTexture::StorageTexture(ProgramID pid,
+                               const Source& src,
+                               TextureDimension d,
+                               ImageFormat fmt,
                                Type* subtype,
-                               Access access)
-    : Base(program_id, source, dim),
-      image_format_(format),
-      subtype_(subtype),
-      access_(access) {}
+                               Access ac)
+    : Base(pid, src, d), format(fmt), type(subtype), access(ac) {}
 
 StorageTexture::StorageTexture(StorageTexture&&) = default;
 
@@ -157,17 +154,15 @@
 
 std::string StorageTexture::FriendlyName(const SymbolTable&) const {
   std::ostringstream out;
-  out << "texture_storage_" << dim() << "<" << image_format_ << ", " << access_
-      << ">";
+  out << "texture_storage_" << dim << "<" << format << ", " << access << ">";
   return out.str();
 }
 
 StorageTexture* StorageTexture::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* ty = ctx->Clone(type());
-  return ctx->dst->create<StorageTexture>(src, dim(), image_format(), ty,
-                                          access());
+  auto src = ctx->Clone(source);
+  auto* ty = ctx->Clone(type);
+  return ctx->dst->create<StorageTexture>(src, dim, format, ty, access);
 }
 
 Type* StorageTexture::SubtypeFor(ImageFormat format, ProgramBuilder& builder) {
diff --git a/src/ast/storage_texture.h b/src/ast/storage_texture.h
index c89a230..d09bb1a 100644
--- a/src/ast/storage_texture.h
+++ b/src/ast/storage_texture.h
@@ -74,14 +74,14 @@
 class StorageTexture : public Castable<StorageTexture, Texture> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param dim the dimensionality of the texture
   /// @param format the image format of the texture
   /// @param subtype the storage subtype. Use SubtypeFor() to calculate this.
   /// @param access_control the access control for the texture.
-  StorageTexture(ProgramID program_id,
-                 const Source& source,
+  StorageTexture(ProgramID pid,
+                 const Source& src,
                  TextureDimension dim,
                  ImageFormat format,
                  Type* subtype,
@@ -91,22 +91,6 @@
   StorageTexture(StorageTexture&&);
   ~StorageTexture() override;
 
-  /// @returns the image format
-  ImageFormat image_format() const { return image_format_; }
-
-  /// @returns the storage subtype
-  Type* type() const { return subtype_; }
-
-  /// @returns the access control
-  Access access() const { return access_; }
-
-  /// @returns true if the access control is read only
-  bool is_read_only() const { return access_ == Access::kRead; }
-  /// @returns true if the access control is write only
-  bool is_write_only() const { return access_ == Access::kWrite; }
-  /// @returns true if the access control is read/write
-  bool is_read_write() const { return access_ == Access::kReadWrite; }
-
   /// @param symbols the program's symbol table
   /// @returns the name for this type that closely resembles how it would be
   /// declared in WGSL.
@@ -122,10 +106,14 @@
   /// @returns the storage texture subtype for the given ImageFormat
   static Type* SubtypeFor(ImageFormat format, ProgramBuilder& builder);
 
- private:
-  ImageFormat const image_format_;
-  Type* const subtype_;
-  Access const access_;
+  /// The image format
+  ImageFormat const format;
+
+  /// The storage subtype
+  Type* const type;
+
+  /// The access control
+  Access const access;
 };
 
 }  // namespace ast
diff --git a/src/ast/storage_texture_test.cc b/src/ast/storage_texture_test.cc
index 7642282..ecd2c13 100644
--- a/src/ast/storage_texture_test.cc
+++ b/src/ast/storage_texture_test.cc
@@ -37,7 +37,7 @@
   auto* s =
       create<StorageTexture>(TextureDimension::k2dArray,
                              ImageFormat::kRgba32Float, subtype, Access::kRead);
-  EXPECT_EQ(s->dim(), TextureDimension::k2dArray);
+  EXPECT_EQ(s->dim, TextureDimension::k2dArray);
 }
 
 TEST_F(AstStorageTextureTest, Format) {
@@ -45,7 +45,7 @@
   auto* s =
       create<StorageTexture>(TextureDimension::k2dArray,
                              ImageFormat::kRgba32Float, subtype, Access::kRead);
-  EXPECT_EQ(s->image_format(), ImageFormat::kRgba32Float);
+  EXPECT_EQ(s->format, ImageFormat::kRgba32Float);
 }
 
 TEST_F(AstStorageTextureTest, FriendlyName) {
@@ -65,7 +65,7 @@
 
   ASSERT_TRUE(s->Is<Texture>());
   ASSERT_TRUE(s->Is<StorageTexture>());
-  EXPECT_TRUE(s->As<StorageTexture>()->type()->Is<F32>());
+  EXPECT_TRUE(s->As<StorageTexture>()->type->Is<F32>());
 }
 
 TEST_F(AstStorageTextureTest, U32) {
@@ -76,7 +76,7 @@
 
   ASSERT_TRUE(s->Is<Texture>());
   ASSERT_TRUE(s->Is<StorageTexture>());
-  EXPECT_TRUE(s->As<StorageTexture>()->type()->Is<U32>());
+  EXPECT_TRUE(s->As<StorageTexture>()->type->Is<U32>());
 }
 
 TEST_F(AstStorageTextureTest, I32) {
@@ -87,7 +87,7 @@
 
   ASSERT_TRUE(s->Is<Texture>());
   ASSERT_TRUE(s->Is<StorageTexture>());
-  EXPECT_TRUE(s->As<StorageTexture>()->type()->Is<I32>());
+  EXPECT_TRUE(s->As<StorageTexture>()->type->Is<I32>());
 }
 
 }  // namespace
diff --git a/src/ast/stride_decoration.cc b/src/ast/stride_decoration.cc
index 1a4c47b..08d7ee9 100644
--- a/src/ast/stride_decoration.cc
+++ b/src/ast/stride_decoration.cc
@@ -23,21 +23,19 @@
 namespace tint {
 namespace ast {
 
-StrideDecoration::StrideDecoration(ProgramID program_id,
-                                   const Source& source,
-                                   uint32_t stride)
-    : Base(program_id, source), stride_(stride) {}
+StrideDecoration::StrideDecoration(ProgramID pid, const Source& src, uint32_t s)
+    : Base(pid, src), stride(s) {}
 
 StrideDecoration::~StrideDecoration() = default;
 
-std::string StrideDecoration::name() const {
+std::string StrideDecoration::Name() const {
   return "stride";
 }
 
 StrideDecoration* StrideDecoration::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<StrideDecoration>(src, stride_);
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<StrideDecoration>(src, stride);
 }
 
 }  // namespace ast
diff --git a/src/ast/stride_decoration.h b/src/ast/stride_decoration.h
index 6d0a92c..c9cf3e3 100644
--- a/src/ast/stride_decoration.h
+++ b/src/ast/stride_decoration.h
@@ -26,17 +26,14 @@
 class StrideDecoration : public Castable<StrideDecoration, Decoration> {
  public:
   /// constructor
-  /// @param program_id the identifier of the program that owns this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param stride the stride value
-  /// @param source the source of this decoration
-  StrideDecoration(ProgramID program_id, const Source& source, uint32_t stride);
+  StrideDecoration(ProgramID pid, const Source& src, uint32_t stride);
   ~StrideDecoration() override;
 
-  /// @returns the stride value
-  uint32_t stride() const { return stride_; }
-
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -44,8 +41,8 @@
   /// @return the newly cloned node
   StrideDecoration* Clone(CloneContext* ctx) const override;
 
- private:
-  uint32_t const stride_;
+  /// The stride value
+  uint32_t const stride;
 };
 
 }  // namespace ast
diff --git a/src/ast/stride_decoration_test.cc b/src/ast/stride_decoration_test.cc
index 1e25ad3..066b46a 100644
--- a/src/ast/stride_decoration_test.cc
+++ b/src/ast/stride_decoration_test.cc
@@ -22,17 +22,16 @@
 
 TEST_F(StrideDecorationTest, Creation) {
   auto* d = create<StrideDecoration>(2);
-  EXPECT_EQ(2u, d->stride());
+  EXPECT_EQ(2u, d->stride);
 }
 
-
 TEST_F(StrideDecorationTest, Source) {
   auto* d = create<StrideDecoration>(
       Source{Source::Range{Source::Location{1, 2}, Source::Location{3, 4}}}, 2);
-  EXPECT_EQ(d->source().range.begin.line, 1u);
-  EXPECT_EQ(d->source().range.begin.column, 2u);
-  EXPECT_EQ(d->source().range.end.line, 3u);
-  EXPECT_EQ(d->source().range.end.column, 4u);
+  EXPECT_EQ(d->source.range.begin.line, 1u);
+  EXPECT_EQ(d->source.range.begin.column, 2u);
+  EXPECT_EQ(d->source.range.end.line, 3u);
+  EXPECT_EQ(d->source.range.end.column, 4u);
 }
 
 }  // namespace
diff --git a/src/ast/struct.cc b/src/ast/struct.cc
index b49dd28..cb91067 100644
--- a/src/ast/struct.cc
+++ b/src/ast/struct.cc
@@ -24,19 +24,17 @@
 namespace tint {
 namespace ast {
 
-Struct::Struct(ProgramID program_id,
-               const Source& source,
-               Symbol name,
-               StructMemberList members,
-               DecorationList decorations)
-    : Base(program_id, source, name),
-      members_(std::move(members)),
-      decorations_(std::move(decorations)) {
-  for (auto* mem : members_) {
+Struct::Struct(ProgramID pid,
+               const Source& src,
+               Symbol n,
+               StructMemberList m,
+               DecorationList decos)
+    : Base(pid, src, n), members(std::move(m)), decorations(std::move(decos)) {
+  for (auto* mem : members) {
     TINT_ASSERT(AST, mem);
     TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, mem, program_id);
   }
-  for (auto* deco : decorations_) {
+  for (auto* deco : decorations) {
     TINT_ASSERT(AST, deco);
     TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, deco, program_id);
   }
@@ -46,25 +44,16 @@
 
 Struct::~Struct() = default;
 
-StructMember* Struct::get_member(const Symbol& symbol) const {
-  for (auto* mem : members_) {
-    if (mem->symbol() == symbol) {
-      return mem;
-    }
-  }
-  return nullptr;
-}
-
 bool Struct::IsBlockDecorated() const {
-  return HasDecoration<StructBlockDecoration>(decorations_);
+  return HasDecoration<StructBlockDecoration>(decorations);
 }
 
 Struct* Struct::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto n = ctx->Clone(name());
-  auto mem = ctx->Clone(members());
-  auto decos = ctx->Clone(decorations());
+  auto src = ctx->Clone(source);
+  auto n = ctx->Clone(name);
+  auto mem = ctx->Clone(members);
+  auto decos = ctx->Clone(decorations);
   return ctx->dst->create<Struct>(src, n, mem, decos);
 }
 
diff --git a/src/ast/struct.h b/src/ast/struct.h
index dcc5b59..beecd27 100644
--- a/src/ast/struct.h
+++ b/src/ast/struct.h
@@ -29,13 +29,13 @@
 class Struct : public Castable<Struct, TypeDecl> {
  public:
   /// Create a new struct statement
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source The input source for the import statement
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node for the import statement
   /// @param name The name of the structure
   /// @param members The struct members
   /// @param decorations The struct decorations
-  Struct(ProgramID program_id,
-         const Source& source,
+  Struct(ProgramID pid,
+         const Source& src,
          Symbol name,
          StructMemberList members,
          DecorationList decorations);
@@ -44,17 +44,6 @@
 
   ~Struct() override;
 
-  /// @returns the struct decorations
-  const DecorationList& decorations() const { return decorations_; }
-
-  /// @returns the members
-  const StructMemberList& members() const { return members_; }
-
-  /// Returns the struct member with the given symbol or nullptr if non exists.
-  /// @param symbol the symbol of the member
-  /// @returns the struct member or nullptr if not found
-  StructMember* get_member(const Symbol& symbol) const;
-
   /// @returns true if the struct is block decorated
   bool IsBlockDecorated() const;
 
@@ -64,11 +53,14 @@
   /// @return the newly cloned node
   Struct* Clone(CloneContext* ctx) const override;
 
+  /// The members
+  StructMemberList const members;
+
+  /// The struct decorations
+  DecorationList const decorations;
+
  private:
   Struct(const Struct&) = delete;
-
-  StructMemberList const members_;
-  DecorationList const decorations_;
 };
 
 }  // namespace ast
diff --git a/src/ast/struct_block_decoration.cc b/src/ast/struct_block_decoration.cc
index a83d828..e41b34e 100644
--- a/src/ast/struct_block_decoration.cc
+++ b/src/ast/struct_block_decoration.cc
@@ -23,19 +23,18 @@
 namespace tint {
 namespace ast {
 
-StructBlockDecoration::StructBlockDecoration(ProgramID program_id,
-                                             const Source& source)
-    : Base(program_id, source) {}
+StructBlockDecoration::StructBlockDecoration(ProgramID pid, const Source& src)
+    : Base(pid, src) {}
 
 StructBlockDecoration::~StructBlockDecoration() = default;
 
-std::string StructBlockDecoration::name() const {
+std::string StructBlockDecoration::Name() const {
   return "block";
 }
 
 StructBlockDecoration* StructBlockDecoration::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
+  auto src = ctx->Clone(source);
   return ctx->dst->create<StructBlockDecoration>(src);
 }
 
diff --git a/src/ast/struct_block_decoration.h b/src/ast/struct_block_decoration.h
index 8a304a7..8a3cbff 100644
--- a/src/ast/struct_block_decoration.h
+++ b/src/ast/struct_block_decoration.h
@@ -28,13 +28,13 @@
     : public Castable<StructBlockDecoration, Decoration> {
  public:
   /// constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this decoration
-  StructBlockDecoration(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  StructBlockDecoration(ProgramID pid, const Source& src);
   ~StructBlockDecoration() override;
 
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
diff --git a/src/ast/struct_member.cc b/src/ast/struct_member.cc
index 995aedc..73a3460 100644
--- a/src/ast/struct_member.cc
+++ b/src/ast/struct_member.cc
@@ -21,19 +21,16 @@
 namespace tint {
 namespace ast {
 
-StructMember::StructMember(ProgramID program_id,
-                           const Source& source,
+StructMember::StructMember(ProgramID pid,
+                           const Source& src,
                            const Symbol& sym,
-                           ast::Type* type,
-                           DecorationList decorations)
-    : Base(program_id, source),
-      symbol_(sym),
-      type_(type),
-      decorations_(std::move(decorations)) {
+                           ast::Type* ty,
+                           DecorationList decos)
+    : Base(pid, src), symbol(sym), type(ty), decorations(std::move(decos)) {
   TINT_ASSERT(AST, type);
-  TINT_ASSERT(AST, symbol_.IsValid());
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol_, program_id);
-  for (auto* deco : decorations_) {
+  TINT_ASSERT(AST, symbol.IsValid());
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol, program_id);
+  for (auto* deco : decorations) {
     TINT_ASSERT(AST, deco);
     TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, deco, program_id);
   }
@@ -43,24 +40,12 @@
 
 StructMember::~StructMember() = default;
 
-bool StructMember::has_offset_decoration() const {
-  return HasDecoration<StructMemberOffsetDecoration>(decorations_);
-}
-
-uint32_t StructMember::offset() const {
-  if (auto* offset =
-          GetDecoration<StructMemberOffsetDecoration>(decorations_)) {
-    return offset->offset();
-  }
-  return 0;
-}
-
 StructMember* StructMember::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto sym = ctx->Clone(symbol_);
-  auto* ty = ctx->Clone(type_);
-  auto decos = ctx->Clone(decorations_);
+  auto src = ctx->Clone(source);
+  auto sym = ctx->Clone(symbol);
+  auto* ty = ctx->Clone(type);
+  auto decos = ctx->Clone(decorations);
   return ctx->dst->create<StructMember>(src, sym, ty, decos);
 }
 
diff --git a/src/ast/struct_member.h b/src/ast/struct_member.h
index 6635153..c3865b5 100644
--- a/src/ast/struct_member.h
+++ b/src/ast/struct_member.h
@@ -30,13 +30,13 @@
 class StructMember : public Castable<StructMember, Node> {
  public:
   /// Create a new struct member statement
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source The input source for the struct member statement
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node for the struct member statement
   /// @param sym The struct member symbol
   /// @param type The struct member type
   /// @param decorations The struct member decorations
-  StructMember(ProgramID program_id,
-               const Source& source,
+  StructMember(ProgramID pid,
+               const Source& src,
                const Symbol& sym,
                ast::Type* type,
                DecorationList decorations);
@@ -45,32 +45,23 @@
 
   ~StructMember() override;
 
-  /// @returns the symbol
-  const Symbol& symbol() const { return symbol_; }
-
-  /// @returns the type
-  ast::Type* type() const { return type_; }
-
-  /// @returns the decorations
-  const DecorationList& decorations() const { return decorations_; }
-
-  /// @returns true if the struct member has an offset decoration
-  bool has_offset_decoration() const;
-  /// @returns the offset decoration value.
-  uint32_t offset() const;
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   StructMember* Clone(CloneContext* ctx) const override;
 
+  /// The symbol
+  Symbol const symbol;
+
+  /// The type
+  ast::Type* const type;
+
+  /// The decorations
+  DecorationList const decorations;
+
  private:
   StructMember(const StructMember&) = delete;
-
-  Symbol const symbol_;
-  ast::Type* const type_;
-  DecorationList const decorations_;
 };
 
 /// A list of struct members
diff --git a/src/ast/struct_member_align_decoration.cc b/src/ast/struct_member_align_decoration.cc
index 770e888..e2fb028 100644
--- a/src/ast/struct_member_align_decoration.cc
+++ b/src/ast/struct_member_align_decoration.cc
@@ -24,22 +24,22 @@
 namespace tint {
 namespace ast {
 
-StructMemberAlignDecoration::StructMemberAlignDecoration(ProgramID program_id,
-                                                         const Source& source,
-                                                         uint32_t align)
-    : Base(program_id, source), align_(align) {}
+StructMemberAlignDecoration::StructMemberAlignDecoration(ProgramID pid,
+                                                         const Source& src,
+                                                         uint32_t a)
+    : Base(pid, src), align(a) {}
 
 StructMemberAlignDecoration::~StructMemberAlignDecoration() = default;
 
-std::string StructMemberAlignDecoration::name() const {
+std::string StructMemberAlignDecoration::Name() const {
   return "align";
 }
 
 StructMemberAlignDecoration* StructMemberAlignDecoration::Clone(
     CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<StructMemberAlignDecoration>(src, align_);
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<StructMemberAlignDecoration>(src, align);
 }
 
 }  // namespace ast
diff --git a/src/ast/struct_member_align_decoration.h b/src/ast/struct_member_align_decoration.h
index d25dfae..64c4dfa 100644
--- a/src/ast/struct_member_align_decoration.h
+++ b/src/ast/struct_member_align_decoration.h
@@ -28,19 +28,14 @@
     : public Castable<StructMemberAlignDecoration, Decoration> {
  public:
   /// constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this decoration
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param align the align value
-  StructMemberAlignDecoration(ProgramID program_id,
-                              const Source& source,
-                              uint32_t align);
+  StructMemberAlignDecoration(ProgramID pid, const Source& src, uint32_t align);
   ~StructMemberAlignDecoration() override;
 
-  /// @returns the align value
-  uint32_t align() const { return align_; }
-
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -48,8 +43,8 @@
   /// @return the newly cloned node
   StructMemberAlignDecoration* Clone(CloneContext* ctx) const override;
 
- private:
-  uint32_t const align_;
+  /// The align value
+  uint32_t const align;
 };
 
 }  // namespace ast
diff --git a/src/ast/struct_member_align_decoration_test.cc b/src/ast/struct_member_align_decoration_test.cc
index 8dc71a6..beb545e 100644
--- a/src/ast/struct_member_align_decoration_test.cc
+++ b/src/ast/struct_member_align_decoration_test.cc
@@ -24,7 +24,7 @@
 
 TEST_F(StructMemberAlignDecorationTest, Creation) {
   auto* d = create<StructMemberAlignDecoration>(2);
-  EXPECT_EQ(2u, d->align());
+  EXPECT_EQ(2u, d->align);
 }
 
 }  // namespace
diff --git a/src/ast/struct_member_offset_decoration.cc b/src/ast/struct_member_offset_decoration.cc
index 7939b19..a482fbd 100644
--- a/src/ast/struct_member_offset_decoration.cc
+++ b/src/ast/struct_member_offset_decoration.cc
@@ -23,22 +23,22 @@
 namespace tint {
 namespace ast {
 
-StructMemberOffsetDecoration::StructMemberOffsetDecoration(ProgramID program_id,
-                                                           const Source& source,
-                                                           uint32_t offset)
-    : Base(program_id, source), offset_(offset) {}
+StructMemberOffsetDecoration::StructMemberOffsetDecoration(ProgramID pid,
+                                                           const Source& src,
+                                                           uint32_t o)
+    : Base(pid, src), offset(o) {}
 
 StructMemberOffsetDecoration::~StructMemberOffsetDecoration() = default;
 
-std::string StructMemberOffsetDecoration::name() const {
+std::string StructMemberOffsetDecoration::Name() const {
   return "offset";
 }
 
 StructMemberOffsetDecoration* StructMemberOffsetDecoration::Clone(
     CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<StructMemberOffsetDecoration>(src, offset_);
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<StructMemberOffsetDecoration>(src, offset);
 }
 
 }  // namespace ast
diff --git a/src/ast/struct_member_offset_decoration.h b/src/ast/struct_member_offset_decoration.h
index 8cd9db1..753c647 100644
--- a/src/ast/struct_member_offset_decoration.h
+++ b/src/ast/struct_member_offset_decoration.h
@@ -36,19 +36,16 @@
     : public Castable<StructMemberOffsetDecoration, Decoration> {
  public:
   /// constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this decoration
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param offset the offset value
-  StructMemberOffsetDecoration(ProgramID program_id,
-                               const Source& source,
+  StructMemberOffsetDecoration(ProgramID pid,
+                               const Source& src,
                                uint32_t offset);
   ~StructMemberOffsetDecoration() override;
 
-  /// @returns the offset value
-  uint32_t offset() const { return offset_; }
-
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -56,8 +53,8 @@
   /// @return the newly cloned node
   StructMemberOffsetDecoration* Clone(CloneContext* ctx) const override;
 
- private:
-  uint32_t const offset_;
+  /// The offset value
+  uint32_t const offset;
 };
 
 }  // namespace ast
diff --git a/src/ast/struct_member_offset_decoration_test.cc b/src/ast/struct_member_offset_decoration_test.cc
index 94f3e87..d04e1a0 100644
--- a/src/ast/struct_member_offset_decoration_test.cc
+++ b/src/ast/struct_member_offset_decoration_test.cc
@@ -22,7 +22,7 @@
 
 TEST_F(StructMemberOffsetDecorationTest, Creation) {
   auto* d = create<StructMemberOffsetDecoration>(2);
-  EXPECT_EQ(2u, d->offset());
+  EXPECT_EQ(2u, d->offset);
 }
 
 }  // namespace
diff --git a/src/ast/struct_member_size_decoration.cc b/src/ast/struct_member_size_decoration.cc
index 1b679c6..0155c41 100644
--- a/src/ast/struct_member_size_decoration.cc
+++ b/src/ast/struct_member_size_decoration.cc
@@ -24,22 +24,22 @@
 namespace tint {
 namespace ast {
 
-StructMemberSizeDecoration::StructMemberSizeDecoration(ProgramID program_id,
-                                                       const Source& source,
-                                                       uint32_t size)
-    : Base(program_id, source), size_(size) {}
+StructMemberSizeDecoration::StructMemberSizeDecoration(ProgramID pid,
+                                                       const Source& src,
+                                                       uint32_t sz)
+    : Base(pid, src), size(sz) {}
 
 StructMemberSizeDecoration::~StructMemberSizeDecoration() = default;
 
-std::string StructMemberSizeDecoration::name() const {
+std::string StructMemberSizeDecoration::Name() const {
   return "size";
 }
 
 StructMemberSizeDecoration* StructMemberSizeDecoration::Clone(
     CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<StructMemberSizeDecoration>(src, size_);
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<StructMemberSizeDecoration>(src, size);
 }
 
 }  // namespace ast
diff --git a/src/ast/struct_member_size_decoration.h b/src/ast/struct_member_size_decoration.h
index 25cfb2a..50bbed0 100644
--- a/src/ast/struct_member_size_decoration.h
+++ b/src/ast/struct_member_size_decoration.h
@@ -28,19 +28,14 @@
     : public Castable<StructMemberSizeDecoration, Decoration> {
  public:
   /// constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this decoration
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param size the size value
-  StructMemberSizeDecoration(ProgramID program_id,
-                             const Source& source,
-                             uint32_t size);
+  StructMemberSizeDecoration(ProgramID pid, const Source& src, uint32_t size);
   ~StructMemberSizeDecoration() override;
 
-  /// @returns the size value
-  uint32_t size() const { return size_; }
-
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -48,8 +43,8 @@
   /// @return the newly cloned node
   StructMemberSizeDecoration* Clone(CloneContext* ctx) const override;
 
- private:
-  uint32_t const size_;
+  /// The size value
+  uint32_t const size;
 };
 
 }  // namespace ast
diff --git a/src/ast/struct_member_size_decoration_test.cc b/src/ast/struct_member_size_decoration_test.cc
index fea6fd2..1e6df5f 100644
--- a/src/ast/struct_member_size_decoration_test.cc
+++ b/src/ast/struct_member_size_decoration_test.cc
@@ -24,7 +24,7 @@
 
 TEST_F(StructMemberOffsetDecorationTest, Creation) {
   auto* d = create<StructMemberSizeDecoration>(2);
-  EXPECT_EQ(2u, d->size());
+  EXPECT_EQ(2u, d->size);
 }
 
 }  // namespace
diff --git a/src/ast/struct_member_test.cc b/src/ast/struct_member_test.cc
index 6bf3edd..c5a1630 100644
--- a/src/ast/struct_member_test.cc
+++ b/src/ast/struct_member_test.cc
@@ -23,27 +23,27 @@
 
 TEST_F(StructMemberTest, Creation) {
   auto* st = Member("a", ty.i32(), {MemberSize(4)});
-  EXPECT_EQ(st->symbol(), Symbol(1, ID()));
-  EXPECT_TRUE(st->type()->Is<ast::I32>());
-  EXPECT_EQ(st->decorations().size(), 1u);
-  EXPECT_TRUE(st->decorations()[0]->Is<StructMemberSizeDecoration>());
-  EXPECT_EQ(st->source().range.begin.line, 0u);
-  EXPECT_EQ(st->source().range.begin.column, 0u);
-  EXPECT_EQ(st->source().range.end.line, 0u);
-  EXPECT_EQ(st->source().range.end.column, 0u);
+  EXPECT_EQ(st->symbol, Symbol(1, ID()));
+  EXPECT_TRUE(st->type->Is<ast::I32>());
+  EXPECT_EQ(st->decorations.size(), 1u);
+  EXPECT_TRUE(st->decorations[0]->Is<StructMemberSizeDecoration>());
+  EXPECT_EQ(st->source.range.begin.line, 0u);
+  EXPECT_EQ(st->source.range.begin.column, 0u);
+  EXPECT_EQ(st->source.range.end.line, 0u);
+  EXPECT_EQ(st->source.range.end.column, 0u);
 }
 
 TEST_F(StructMemberTest, CreationWithSource) {
   auto* st = Member(
       Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 8}}},
       "a", ty.i32());
-  EXPECT_EQ(st->symbol(), Symbol(1, ID()));
-  EXPECT_TRUE(st->type()->Is<ast::I32>());
-  EXPECT_EQ(st->decorations().size(), 0u);
-  EXPECT_EQ(st->source().range.begin.line, 27u);
-  EXPECT_EQ(st->source().range.begin.column, 4u);
-  EXPECT_EQ(st->source().range.end.line, 27u);
-  EXPECT_EQ(st->source().range.end.column, 8u);
+  EXPECT_EQ(st->symbol, Symbol(1, ID()));
+  EXPECT_TRUE(st->type->Is<ast::I32>());
+  EXPECT_EQ(st->decorations.size(), 0u);
+  EXPECT_EQ(st->source.range.begin.line, 27u);
+  EXPECT_EQ(st->source.range.begin.column, 4u);
+  EXPECT_EQ(st->source.range.end.line, 27u);
+  EXPECT_EQ(st->source.range.end.column, 8u);
 }
 
 TEST_F(StructMemberTest, Assert_Empty_Symbol) {
diff --git a/src/ast/struct_test.cc b/src/ast/struct_test.cc
index 7fe50e4..5d1701d 100644
--- a/src/ast/struct_test.cc
+++ b/src/ast/struct_test.cc
@@ -38,13 +38,13 @@
   auto name = Sym("s");
   auto* s = create<Struct>(name, StructMemberList{Member("a", ty.i32())},
                            DecorationList{});
-  EXPECT_EQ(s->name(), name);
-  EXPECT_EQ(s->members().size(), 1u);
-  EXPECT_TRUE(s->decorations().empty());
-  EXPECT_EQ(s->source().range.begin.line, 0u);
-  EXPECT_EQ(s->source().range.begin.column, 0u);
-  EXPECT_EQ(s->source().range.end.line, 0u);
-  EXPECT_EQ(s->source().range.end.column, 0u);
+  EXPECT_EQ(s->name, name);
+  EXPECT_EQ(s->members.size(), 1u);
+  EXPECT_TRUE(s->decorations.empty());
+  EXPECT_EQ(s->source.range.begin.line, 0u);
+  EXPECT_EQ(s->source.range.begin.column, 0u);
+  EXPECT_EQ(s->source.range.end.line, 0u);
+  EXPECT_EQ(s->source.range.end.column, 0u);
 }
 
 TEST_F(AstStructTest, Creation_WithDecorations) {
@@ -54,14 +54,14 @@
 
   auto* s =
       create<Struct>(name, StructMemberList{Member("a", ty.i32())}, decos);
-  EXPECT_EQ(s->name(), name);
-  EXPECT_EQ(s->members().size(), 1u);
-  ASSERT_EQ(s->decorations().size(), 1u);
-  EXPECT_TRUE(s->decorations()[0]->Is<StructBlockDecoration>());
-  EXPECT_EQ(s->source().range.begin.line, 0u);
-  EXPECT_EQ(s->source().range.begin.column, 0u);
-  EXPECT_EQ(s->source().range.end.line, 0u);
-  EXPECT_EQ(s->source().range.end.column, 0u);
+  EXPECT_EQ(s->name, name);
+  EXPECT_EQ(s->members.size(), 1u);
+  ASSERT_EQ(s->decorations.size(), 1u);
+  EXPECT_TRUE(s->decorations[0]->Is<StructBlockDecoration>());
+  EXPECT_EQ(s->source.range.begin.line, 0u);
+  EXPECT_EQ(s->source.range.begin.column, 0u);
+  EXPECT_EQ(s->source.range.end.line, 0u);
+  EXPECT_EQ(s->source.range.end.column, 0u);
 }
 
 TEST_F(AstStructTest, CreationWithSourceAndDecorations) {
@@ -70,14 +70,14 @@
       Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 8}}},
       name, StructMemberList{Member("a", ty.i32())},
       DecorationList{create<StructBlockDecoration>()});
-  EXPECT_EQ(s->name(), name);
-  EXPECT_EQ(s->members().size(), 1u);
-  ASSERT_EQ(s->decorations().size(), 1u);
-  EXPECT_TRUE(s->decorations()[0]->Is<StructBlockDecoration>());
-  EXPECT_EQ(s->source().range.begin.line, 27u);
-  EXPECT_EQ(s->source().range.begin.column, 4u);
-  EXPECT_EQ(s->source().range.end.line, 27u);
-  EXPECT_EQ(s->source().range.end.column, 8u);
+  EXPECT_EQ(s->name, name);
+  EXPECT_EQ(s->members.size(), 1u);
+  ASSERT_EQ(s->decorations.size(), 1u);
+  EXPECT_TRUE(s->decorations[0]->Is<StructBlockDecoration>());
+  EXPECT_EQ(s->source.range.begin.line, 27u);
+  EXPECT_EQ(s->source.range.begin.column, 4u);
+  EXPECT_EQ(s->source.range.end.line, 27u);
+  EXPECT_EQ(s->source.range.end.column, 8u);
 }
 
 TEST_F(AstStructTest, Assert_Null_StructMember) {
diff --git a/src/ast/switch_statement.cc b/src/ast/switch_statement.cc
index 7091b3e..2013fcc 100644
--- a/src/ast/switch_statement.cc
+++ b/src/ast/switch_statement.cc
@@ -21,14 +21,14 @@
 namespace tint {
 namespace ast {
 
-SwitchStatement::SwitchStatement(ProgramID program_id,
-                                 const Source& source,
-                                 Expression* condition,
-                                 CaseStatementList body)
-    : Base(program_id, source), condition_(condition), body_(body) {
-  TINT_ASSERT(AST, condition_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition_, program_id);
-  for (auto* stmt : body_) {
+SwitchStatement::SwitchStatement(ProgramID pid,
+                                 const Source& src,
+                                 Expression* cond,
+                                 CaseStatementList b)
+    : Base(pid, src), condition(cond), body(b) {
+  TINT_ASSERT(AST, condition);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition, program_id);
+  for (auto* stmt : body) {
     TINT_ASSERT(AST, stmt);
     TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, stmt, program_id);
   }
@@ -40,9 +40,9 @@
 
 SwitchStatement* SwitchStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* cond = ctx->Clone(condition());
-  auto b = ctx->Clone(body());
+  auto src = ctx->Clone(source);
+  auto* cond = ctx->Clone(condition);
+  auto b = ctx->Clone(body);
   return ctx->dst->create<SwitchStatement>(src, cond, b);
 }
 
diff --git a/src/ast/switch_statement.h b/src/ast/switch_statement.h
index fae33f5..beec419 100644
--- a/src/ast/switch_statement.h
+++ b/src/ast/switch_statement.h
@@ -25,25 +25,20 @@
 class SwitchStatement : public Castable<SwitchStatement, Statement> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source information
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param condition the switch condition
   /// @param body the switch body
-  SwitchStatement(ProgramID program_id,
-                  const Source& source,
+  SwitchStatement(ProgramID pid,
+                  const Source& src,
                   Expression* condition,
                   CaseStatementList body);
   /// Move constructor
   SwitchStatement(SwitchStatement&&);
   ~SwitchStatement() override;
 
-  /// @returns the switch condition or nullptr if none set
-  Expression* condition() const { return condition_; }
   /// @returns true if this is a default statement
-  bool IsDefault() const { return condition_ == nullptr; }
-
-  /// @returns the Switch body
-  const CaseStatementList& body() const { return body_; }
+  bool IsDefault() const { return condition == nullptr; }
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -51,11 +46,14 @@
   /// @return the newly cloned node
   SwitchStatement* Clone(CloneContext* ctx) const override;
 
+  /// The switch condition or nullptr if none set
+  Expression* const condition;
+
+  /// The Switch body
+  CaseStatementList const body;
+
  private:
   SwitchStatement(const SwitchStatement&) = delete;
-
-  Expression* const condition_;
-  CaseStatementList const body_;
 };
 
 }  // namespace ast
diff --git a/src/ast/switch_statement_test.cc b/src/ast/switch_statement_test.cc
index 66c29e4..355f70f 100644
--- a/src/ast/switch_statement_test.cc
+++ b/src/ast/switch_statement_test.cc
@@ -33,9 +33,9 @@
   body.push_back(case_stmt);
 
   auto* stmt = create<SwitchStatement>(ident, body);
-  EXPECT_EQ(stmt->condition(), ident);
-  ASSERT_EQ(stmt->body().size(), 1u);
-  EXPECT_EQ(stmt->body()[0], case_stmt);
+  EXPECT_EQ(stmt->condition, ident);
+  ASSERT_EQ(stmt->body.size(), 1u);
+  EXPECT_EQ(stmt->body[0], case_stmt);
 }
 
 TEST_F(SwitchStatementTest, Creation_WithSource) {
@@ -43,7 +43,7 @@
 
   auto* stmt = create<SwitchStatement>(Source{Source::Location{20, 2}}, ident,
                                        CaseStatementList());
-  auto src = stmt->source();
+  auto src = stmt->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/texture.cc b/src/ast/texture.cc
index 28de192..6c54e24 100644
--- a/src/ast/texture.cc
+++ b/src/ast/texture.cc
@@ -78,10 +78,8 @@
   return 0;
 }
 
-Texture::Texture(ProgramID program_id,
-                 const Source& source,
-                 TextureDimension dim)
-    : Base(program_id, source), dim_(dim) {}
+Texture::Texture(ProgramID pid, const Source& src, TextureDimension d)
+    : Base(pid, src), dim(d) {}
 
 Texture::Texture(Texture&&) = default;
 
diff --git a/src/ast/texture.h b/src/ast/texture.h
index 4c2270e..769d1eb 100644
--- a/src/ast/texture.h
+++ b/src/ast/texture.h
@@ -65,19 +65,16 @@
 class Texture : public Castable<Texture, Type> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param dim the dimensionality of the texture
-  Texture(ProgramID program_id, const Source& source, TextureDimension dim);
+  Texture(ProgramID pid, const Source& src, TextureDimension dim);
   /// Move constructor
   Texture(Texture&&);
   ~Texture() override;
 
-  /// @returns the texture dimension
-  TextureDimension dim() const { return dim_; }
-
- private:
-  TextureDimension const dim_;
+  /// The texture dimension
+  TextureDimension const dim;
 };
 
 }  // namespace ast
diff --git a/src/ast/type.h b/src/ast/type.h
index c03a2b5..3f60261 100644
--- a/src/ast/type.h
+++ b/src/ast/type.h
@@ -42,9 +42,9 @@
 
  protected:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
-  Type(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  Type(ProgramID pid, const Source& src);
 };
 
 }  // namespace ast
diff --git a/src/ast/type_constructor_expression.cc b/src/ast/type_constructor_expression.cc
index e382b12..bfae88b 100644
--- a/src/ast/type_constructor_expression.cc
+++ b/src/ast/type_constructor_expression.cc
@@ -21,13 +21,13 @@
 namespace tint {
 namespace ast {
 
-TypeConstructorExpression::TypeConstructorExpression(ProgramID program_id,
-                                                     const Source& source,
-                                                     ast::Type* type,
-                                                     ExpressionList values)
-    : Base(program_id, source), type_(type), values_(std::move(values)) {
-  TINT_ASSERT(AST, type_);
-  for (auto* val : values_) {
+TypeConstructorExpression::TypeConstructorExpression(ProgramID pid,
+                                                     const Source& src,
+                                                     ast::Type* ty,
+                                                     ExpressionList vals)
+    : Base(pid, src), type(ty), values(std::move(vals)) {
+  TINT_ASSERT(AST, type);
+  for (auto* val : values) {
     TINT_ASSERT(AST, val);
     TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, val, program_id);
   }
@@ -41,9 +41,9 @@
 TypeConstructorExpression* TypeConstructorExpression::Clone(
     CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* ty = ctx->Clone(type());
-  auto vals = ctx->Clone(values());
+  auto src = ctx->Clone(source);
+  auto* ty = ctx->Clone(type);
+  auto vals = ctx->Clone(values);
   return ctx->dst->create<TypeConstructorExpression>(src, ty, vals);
 }
 
diff --git a/src/ast/type_constructor_expression.h b/src/ast/type_constructor_expression.h
index b23aeeb..f8590d4 100644
--- a/src/ast/type_constructor_expression.h
+++ b/src/ast/type_constructor_expression.h
@@ -30,35 +30,32 @@
     : public Castable<TypeConstructorExpression, ConstructorExpression> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the constructor source
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param type the type
   /// @param values the constructor values
-  TypeConstructorExpression(ProgramID program_id,
-                            const Source& source,
+  TypeConstructorExpression(ProgramID pid,
+                            const Source& src,
                             ast::Type* type,
                             ExpressionList values);
   /// Move constructor
   TypeConstructorExpression(TypeConstructorExpression&&);
   ~TypeConstructorExpression() override;
 
-  /// @returns the type
-  ast::Type* type() const { return type_; }
-
-  /// @returns the values
-  const ExpressionList& values() const { return values_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   TypeConstructorExpression* Clone(CloneContext* ctx) const override;
 
+  /// The type
+  ast::Type* const type;
+
+  /// The values
+  ExpressionList const values;
+
  private:
   TypeConstructorExpression(const TypeConstructorExpression&) = delete;
-
-  ast::Type* const type_;
-  ExpressionList const values_;
 };
 
 }  // namespace ast
diff --git a/src/ast/type_constructor_expression_test.cc b/src/ast/type_constructor_expression_test.cc
index 7ef5eb8..fa87cc5 100644
--- a/src/ast/type_constructor_expression_test.cc
+++ b/src/ast/type_constructor_expression_test.cc
@@ -26,9 +26,9 @@
   expr.push_back(Expr("expr"));
 
   auto* t = create<TypeConstructorExpression>(ty.f32(), expr);
-  EXPECT_TRUE(t->type()->Is<ast::F32>());
-  ASSERT_EQ(t->values().size(), 1u);
-  EXPECT_EQ(t->values()[0], expr[0]);
+  EXPECT_TRUE(t->type->Is<ast::F32>());
+  ASSERT_EQ(t->values.size(), 1u);
+  EXPECT_EQ(t->values[0], expr[0]);
 }
 
 TEST_F(TypeConstructorExpressionTest, Creation_WithSource) {
@@ -37,7 +37,7 @@
 
   auto* t = create<TypeConstructorExpression>(Source{Source::Location{20, 2}},
                                               ty.f32(), expr);
-  auto src = t->source();
+  auto src = t->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/type_decl.cc b/src/ast/type_decl.cc
index 41491ee..94c94af 100644
--- a/src/ast/type_decl.cc
+++ b/src/ast/type_decl.cc
@@ -21,8 +21,8 @@
 namespace tint {
 namespace ast {
 
-TypeDecl::TypeDecl(ProgramID program_id, const Source& source, Symbol name)
-    : Base(program_id, source), name_(name) {
+TypeDecl::TypeDecl(ProgramID pid, const Source& src, Symbol n)
+    : Base(pid, src), name(n) {
   TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, name, program_id);
 }
 
diff --git a/src/ast/type_decl.h b/src/ast/type_decl.h
index 0f5c7a8..df6b94d 100644
--- a/src/ast/type_decl.h
+++ b/src/ast/type_decl.h
@@ -26,23 +26,21 @@
 class TypeDecl : public Castable<TypeDecl, Node> {
  public:
   /// Create a new struct statement
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source The input source for the import statement
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node for the import statement
   /// @param name The name of the structure
-  TypeDecl(ProgramID program_id, const Source& source, Symbol name);
+  TypeDecl(ProgramID pid, const Source& src, Symbol name);
   /// Move constructor
   TypeDecl(TypeDecl&&);
 
   ~TypeDecl() override;
 
-  /// @returns the name of the type declaration
-  Symbol name() const { return name_; }
+  /// The name of the type declaration
+  Symbol const name;
 
  private:
   TypeDecl(const TypeDecl&) = delete;
   TypeDecl& operator=(const TypeDecl&) = delete;
-
-  Symbol const name_;
 };
 
 }  // namespace ast
diff --git a/src/ast/type_name.cc b/src/ast/type_name.cc
index 943e66f..3ad3236 100644
--- a/src/ast/type_name.cc
+++ b/src/ast/type_name.cc
@@ -21,20 +21,20 @@
 namespace tint {
 namespace ast {
 
-TypeName::TypeName(ProgramID program_id, const Source& source, Symbol name)
-    : Base(program_id, source), name_(name) {}
+TypeName::TypeName(ProgramID pid, const Source& src, Symbol n)
+    : Base(pid, src), name(n) {}
 
 TypeName::~TypeName() = default;
 
 TypeName::TypeName(TypeName&&) = default;
 
 std::string TypeName::FriendlyName(const SymbolTable& symbols) const {
-  return symbols.NameFor(name_);
+  return symbols.NameFor(name);
 }
 
 TypeName* TypeName::Clone(CloneContext* ctx) const {
-  auto src = ctx->Clone(source());
-  auto n = ctx->Clone(name());
+  auto src = ctx->Clone(source);
+  auto n = ctx->Clone(name);
   return ctx->dst->create<TypeName>(src, n);
 }
 
diff --git a/src/ast/type_name.h b/src/ast/type_name.h
index fb4cc8c..867bc96 100644
--- a/src/ast/type_name.h
+++ b/src/ast/type_name.h
@@ -26,17 +26,15 @@
 class TypeName : public Castable<TypeName, Type> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param name the type name
-  TypeName(ProgramID program_id, const Source& source, Symbol name);
+  TypeName(ProgramID pid, const Source& src, Symbol name);
   /// Move constructor
   TypeName(TypeName&&);
   /// Destructor
   ~TypeName() override;
 
-  /// @return the type name
-  const Symbol& name() const { return name_; }
 
   /// @param symbols the program's symbol table
   /// @returns the name for this type that closely resembles how it would be
@@ -48,8 +46,8 @@
   /// @return the newly cloned type
   TypeName* Clone(CloneContext* ctx) const override;
 
- private:
-  Symbol name_;
+  /// The type name
+  Symbol name;
 };
 
 }  // namespace ast
diff --git a/src/ast/u32.cc b/src/ast/u32.cc
index 21bcc16..9337861 100644
--- a/src/ast/u32.cc
+++ b/src/ast/u32.cc
@@ -21,8 +21,7 @@
 namespace tint {
 namespace ast {
 
-U32::U32(ProgramID program_id, const Source& source)
-    : Base(program_id, source) {}
+U32::U32(ProgramID pid, const Source& src) : Base(pid, src) {}
 
 U32::~U32() = default;
 
@@ -33,7 +32,7 @@
 }
 
 U32* U32::Clone(CloneContext* ctx) const {
-  auto src = ctx->Clone(source());
+  auto src = ctx->Clone(source);
   return ctx->dst->create<U32>(src);
 }
 
diff --git a/src/ast/u32.h b/src/ast/u32.h
index 2acf667..6671429 100644
--- a/src/ast/u32.h
+++ b/src/ast/u32.h
@@ -26,9 +26,9 @@
 class U32 : public Castable<U32, Type> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
-  U32(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  U32(ProgramID pid, const Source& src);
   /// Move constructor
   U32(U32&&);
   ~U32() override;
diff --git a/src/ast/uint_literal.cc b/src/ast/uint_literal.cc
index c00846e..b25db81 100644
--- a/src/ast/uint_literal.cc
+++ b/src/ast/uint_literal.cc
@@ -21,21 +21,19 @@
 namespace tint {
 namespace ast {
 
-UintLiteral::UintLiteral(ProgramID program_id,
-                         const Source& source,
-                         uint32_t value)
-    : Base(program_id, source, value) {}
+UintLiteral::UintLiteral(ProgramID pid, const Source& src, uint32_t val)
+    : Base(pid, src), value(val) {}
 
 UintLiteral::~UintLiteral() = default;
 
-std::string UintLiteral::name() const {
-  return "__uint" + std::to_string(value());
+uint32_t UintLiteral::ValueAsU32() const {
+  return value;
 }
 
 UintLiteral* UintLiteral::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  return ctx->dst->create<UintLiteral>(src, value());
+  auto src = ctx->Clone(source);
+  return ctx->dst->create<UintLiteral>(src, value);
 }
 
 }  // namespace ast
diff --git a/src/ast/uint_literal.h b/src/ast/uint_literal.h
index f6b084e..3a2df62 100644
--- a/src/ast/uint_literal.h
+++ b/src/ast/uint_literal.h
@@ -26,23 +26,23 @@
 class UintLiteral : public Castable<UintLiteral, IntLiteral> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the input source
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param value the uint literals value
-  UintLiteral(ProgramID program_id, const Source& source, uint32_t value);
+  UintLiteral(ProgramID pid, const Source& src, uint32_t value);
   ~UintLiteral() override;
 
-  /// @returns the uint literal value
-  uint32_t value() const { return value_as_u32(); }
-
-  /// @returns the name for this literal. This name is unique to this value.
-  std::string name() const override;
+  /// @returns the literal value as a u32
+  uint32_t ValueAsU32() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   UintLiteral* Clone(CloneContext* ctx) const override;
+
+  /// The int literal value
+  uint32_t const value;
 };
 
 }  // namespace ast
diff --git a/src/ast/uint_literal_test.cc b/src/ast/uint_literal_test.cc
index 1da417d..a65750a 100644
--- a/src/ast/uint_literal_test.cc
+++ b/src/ast/uint_literal_test.cc
@@ -23,7 +23,7 @@
 TEST_F(UintLiteralTest, Value) {
   auto* u = create<UintLiteral>(47);
   ASSERT_TRUE(u->Is<UintLiteral>());
-  EXPECT_EQ(u->value(), 47u);
+  EXPECT_EQ(u->value, 47u);
 }
 
 }  // namespace
diff --git a/src/ast/unary_op_expression.cc b/src/ast/unary_op_expression.cc
index 52eb687..21ebfec 100644
--- a/src/ast/unary_op_expression.cc
+++ b/src/ast/unary_op_expression.cc
@@ -21,13 +21,13 @@
 namespace tint {
 namespace ast {
 
-UnaryOpExpression::UnaryOpExpression(ProgramID program_id,
-                                     const Source& source,
-                                     UnaryOp op,
-                                     Expression* expr)
-    : Base(program_id, source), op_(op), expr_(expr) {
-  TINT_ASSERT(AST, expr_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, expr_, program_id);
+UnaryOpExpression::UnaryOpExpression(ProgramID pid,
+                                     const Source& src,
+                                     UnaryOp o,
+                                     Expression* e)
+    : Base(pid, src), op(o), expr(e) {
+  TINT_ASSERT(AST, expr);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, expr, program_id);
 }
 
 UnaryOpExpression::UnaryOpExpression(UnaryOpExpression&&) = default;
@@ -36,9 +36,9 @@
 
 UnaryOpExpression* UnaryOpExpression::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* e = ctx->Clone(expr());
-  return ctx->dst->create<UnaryOpExpression>(src, op_, e);
+  auto src = ctx->Clone(source);
+  auto* e = ctx->Clone(expr);
+  return ctx->dst->create<UnaryOpExpression>(src, op, e);
 }
 
 }  // namespace ast
diff --git a/src/ast/unary_op_expression.h b/src/ast/unary_op_expression.h
index 94f3137..03345f5 100644
--- a/src/ast/unary_op_expression.h
+++ b/src/ast/unary_op_expression.h
@@ -37,22 +37,20 @@
   UnaryOpExpression(UnaryOpExpression&&);
   ~UnaryOpExpression() override;
 
-  /// @returns the op
-  UnaryOp op() const { return op_; }
-  /// @returns the expression
-  Expression* expr() const { return expr_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   UnaryOpExpression* Clone(CloneContext* ctx) const override;
 
+  /// The op
+  UnaryOp const op;
+
+  /// The expression
+  Expression* const expr;
+
  private:
   UnaryOpExpression(const UnaryOpExpression&) = delete;
-
-  UnaryOp const op_;
-  Expression* const expr_;
 };
 
 }  // namespace ast
diff --git a/src/ast/unary_op_expression_test.cc b/src/ast/unary_op_expression_test.cc
index db11eff..47f870a 100644
--- a/src/ast/unary_op_expression_test.cc
+++ b/src/ast/unary_op_expression_test.cc
@@ -27,15 +27,15 @@
   auto* ident = Expr("ident");
 
   auto* u = create<UnaryOpExpression>(UnaryOp::kNot, ident);
-  EXPECT_EQ(u->op(), UnaryOp::kNot);
-  EXPECT_EQ(u->expr(), ident);
+  EXPECT_EQ(u->op, UnaryOp::kNot);
+  EXPECT_EQ(u->expr, ident);
 }
 
 TEST_F(UnaryOpExpressionTest, Creation_WithSource) {
   auto* ident = Expr("ident");
   auto* u = create<UnaryOpExpression>(Source{Source::Location{20, 2}},
                                       UnaryOp::kNot, ident);
-  auto src = u->source();
+  auto src = u->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/variable.cc b/src/ast/variable.cc
index c355054..f5da167 100644
--- a/src/ast/variable.cc
+++ b/src/ast/variable.cc
@@ -23,25 +23,25 @@
 namespace tint {
 namespace ast {
 
-Variable::Variable(ProgramID program_id,
-                   const Source& source,
+Variable::Variable(ProgramID pid,
+                   const Source& src,
                    const Symbol& sym,
-                   StorageClass declared_storage_class,
-                   Access declared_access,
-                   const ast::Type* type,
-                   bool is_const,
-                   Expression* constructor,
-                   DecorationList decorations)
-    : Base(program_id, source),
-      symbol_(sym),
-      type_(type),
-      is_const_(is_const),
-      constructor_(constructor),
-      decorations_(std::move(decorations)),
-      declared_storage_class_(declared_storage_class),
-      declared_access_(declared_access) {
-  TINT_ASSERT(AST, symbol_.IsValid());
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol_, program_id);
+                   StorageClass dsc,
+                   Access da,
+                   const ast::Type* ty,
+                   bool constant,
+                   Expression* ctor,
+                   DecorationList decos)
+    : Base(pid, src),
+      symbol(sym),
+      type(const_cast<Type*>(ty)),
+      is_const(constant),
+      constructor(ctor),
+      decorations(std::move(decos)),
+      declared_storage_class(dsc),
+      declared_access(da) {
+  TINT_ASSERT(AST, symbol.IsValid());
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol, program_id);
   TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, constructor, program_id);
 }
 
@@ -49,28 +49,27 @@
 
 Variable::~Variable() = default;
 
-Variable::BindingPoint Variable::binding_point() const {
+VariableBindingPoint Variable::BindingPoint() const {
   GroupDecoration* group = nullptr;
   BindingDecoration* binding = nullptr;
-  for (auto* deco : decorations()) {
+  for (auto* deco : decorations) {
     if (auto* g = deco->As<GroupDecoration>()) {
       group = g;
     } else if (auto* b = deco->As<BindingDecoration>()) {
       binding = b;
     }
   }
-  return BindingPoint{group, binding};
+  return VariableBindingPoint{group, binding};
 }
 
 Variable* Variable::Clone(CloneContext* ctx) const {
-  auto src = ctx->Clone(source());
-  auto sym = ctx->Clone(symbol());
-  auto* ty = ctx->Clone(type());
-  auto* ctor = ctx->Clone(constructor());
-  auto decos = ctx->Clone(decorations());
-  return ctx->dst->create<Variable>(src, sym, declared_storage_class(),
-                                    declared_access(), ty, is_const_, ctor,
-                                    decos);
+  auto src = ctx->Clone(source);
+  auto sym = ctx->Clone(symbol);
+  auto* ty = ctx->Clone(type);
+  auto* ctor = ctx->Clone(constructor);
+  auto decos = ctx->Clone(decorations);
+  return ctx->dst->create<Variable>(src, sym, declared_storage_class,
+                                    declared_access, ty, is_const, ctor, decos);
 }
 
 }  // namespace ast
diff --git a/src/ast/variable.h b/src/ast/variable.h
index 2cbeaf2..b02db6e 100644
--- a/src/ast/variable.h
+++ b/src/ast/variable.h
@@ -32,6 +32,18 @@
 class LocationDecoration;
 class Type;
 
+/// VariableBindingPoint holds a group and binding decoration.
+struct VariableBindingPoint {
+  /// The `[[group]]` part of the binding point
+  GroupDecoration* group = nullptr;
+  /// The `[[binding]]` part of the binding point
+  BindingDecoration* binding = nullptr;
+
+  /// @returns true if the BindingPoint has a valid group and binding
+  /// decoration.
+  inline operator bool() const { return group && binding; }
+};
+
 /// A Variable statement.
 ///
 /// An instance of this class represents one of three constructs in WGSL: "var"
@@ -87,18 +99,6 @@
 ///   - formal parameter is always StorageClass::kNone.
 class Variable : public Castable<Variable, Node> {
  public:
-  /// BindingPoint holds a group and binding decoration.
-  struct BindingPoint {
-    /// The `[[group]]` part of the binding point
-    GroupDecoration* group = nullptr;
-    /// The `[[binding]]` part of the binding point
-    BindingDecoration* binding = nullptr;
-
-    /// @returns true if the BindingPoint has a valid group and binding
-    /// decoration.
-    inline operator bool() const { return group && binding; }
-  };
-
   /// Create a variable
   /// @param program_id the identifier of the program that owns this node
   /// @param source the variable source
@@ -123,33 +123,8 @@
 
   ~Variable() override;
 
-  /// @returns the variable symbol
-  const Symbol& symbol() const { return symbol_; }
-
-  /// @returns the variable type
-  ast::Type* type() const { return const_cast<ast::Type*>(type_); }
-
-  /// @returns the declared storage class
-  StorageClass declared_storage_class() const {
-    return declared_storage_class_;
-  }
-
-  /// @returns the declared access control
-  Access declared_access() const { return declared_access_; }
-
-  /// @returns the constructor expression or nullptr if none set
-  Expression* constructor() const { return constructor_; }
-  /// @returns true if the variable has an constructor
-  bool has_constructor() const { return constructor_ != nullptr; }
-
-  /// @returns true if this is a constant, false otherwise
-  bool is_const() const { return is_const_; }
-
-  /// @returns the decorations attached to this variable
-  const DecorationList& decorations() const { return decorations_; }
-
   /// @returns the binding point information for the variable
-  BindingPoint binding_point() const;
+  VariableBindingPoint BindingPoint() const;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -157,17 +132,29 @@
   /// @return the newly cloned node
   Variable* Clone(CloneContext* ctx) const override;
 
+  /// The variable symbol
+  Symbol const symbol;
+
+  /// The variable type
+  ast::Type* const type;
+
+  /// True if this is a constant, false otherwise
+  bool const is_const;
+
+  /// The constructor expression or nullptr if none set
+  Expression* const constructor;
+
+  /// The decorations attached to this variable
+  DecorationList const decorations;
+
+  /// The declared storage class
+  StorageClass const declared_storage_class;
+
+  /// The declared access control
+  Access const declared_access;
+
  private:
   Variable(const Variable&) = delete;
-
-  Symbol const symbol_;
-  // The value type if a const or formal paramter, and the store type if a var
-  ast::Type const* const type_;
-  bool const is_const_;
-  Expression* const constructor_;
-  DecorationList const decorations_;
-  StorageClass const declared_storage_class_;
-  Access const declared_access_;
 };
 
 /// A list of variables
diff --git a/src/ast/variable_decl_statement.cc b/src/ast/variable_decl_statement.cc
index b686a83..d4ffaca 100644
--- a/src/ast/variable_decl_statement.cc
+++ b/src/ast/variable_decl_statement.cc
@@ -21,12 +21,12 @@
 namespace tint {
 namespace ast {
 
-VariableDeclStatement::VariableDeclStatement(ProgramID program_id,
-                                             const Source& source,
-                                             Variable* variable)
-    : Base(program_id, source), variable_(variable) {
-  TINT_ASSERT(AST, variable_);
-  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, variable_, program_id);
+VariableDeclStatement::VariableDeclStatement(ProgramID pid,
+                                             const Source& src,
+                                             Variable* var)
+    : Base(pid, src), variable(var) {
+  TINT_ASSERT(AST, variable);
+  TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, variable, program_id);
 }
 
 VariableDeclStatement::VariableDeclStatement(VariableDeclStatement&&) = default;
@@ -35,8 +35,8 @@
 
 VariableDeclStatement* VariableDeclStatement::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* var = ctx->Clone(variable());
+  auto src = ctx->Clone(source);
+  auto* var = ctx->Clone(variable);
   return ctx->dst->create<VariableDeclStatement>(src, var);
 }
 
diff --git a/src/ast/variable_decl_statement.h b/src/ast/variable_decl_statement.h
index f1b3083..ef67ded 100644
--- a/src/ast/variable_decl_statement.h
+++ b/src/ast/variable_decl_statement.h
@@ -36,19 +36,17 @@
   VariableDeclStatement(VariableDeclStatement&&);
   ~VariableDeclStatement() override;
 
-  /// @returns the variable
-  Variable* variable() const { return variable_; }
-
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
   /// @param ctx the clone context
   /// @return the newly cloned node
   VariableDeclStatement* Clone(CloneContext* ctx) const override;
 
+  /// The variable
+  Variable* const variable;
+
  private:
   VariableDeclStatement(const VariableDeclStatement&) = delete;
-
-  Variable* const variable_;
 };
 
 }  // namespace ast
diff --git a/src/ast/variable_decl_statement_test.cc b/src/ast/variable_decl_statement_test.cc
index cb61967..bcf92ad 100644
--- a/src/ast/variable_decl_statement_test.cc
+++ b/src/ast/variable_decl_statement_test.cc
@@ -27,7 +27,7 @@
   auto* var = Var("a", ty.f32(), StorageClass::kNone);
 
   auto* stmt = create<VariableDeclStatement>(var);
-  EXPECT_EQ(stmt->variable(), var);
+  EXPECT_EQ(stmt->variable, var);
 }
 
 TEST_F(VariableDeclStatementTest, Creation_WithSource) {
@@ -35,7 +35,7 @@
 
   auto* stmt =
       create<VariableDeclStatement>(Source{Source::Location{20, 2}}, var);
-  auto src = stmt->source();
+  auto src = stmt->source;
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
diff --git a/src/ast/variable_test.cc b/src/ast/variable_test.cc
index 9f29307..a78775b 100644
--- a/src/ast/variable_test.cc
+++ b/src/ast/variable_test.cc
@@ -25,13 +25,13 @@
 TEST_F(VariableTest, Creation) {
   auto* v = Var("my_var", ty.i32(), StorageClass::kFunction);
 
-  EXPECT_EQ(v->symbol(), Symbol(1, ID()));
-  EXPECT_EQ(v->declared_storage_class(), StorageClass::kFunction);
-  EXPECT_TRUE(v->type()->Is<ast::I32>());
-  EXPECT_EQ(v->source().range.begin.line, 0u);
-  EXPECT_EQ(v->source().range.begin.column, 0u);
-  EXPECT_EQ(v->source().range.end.line, 0u);
-  EXPECT_EQ(v->source().range.end.column, 0u);
+  EXPECT_EQ(v->symbol, Symbol(1, ID()));
+  EXPECT_EQ(v->declared_storage_class, StorageClass::kFunction);
+  EXPECT_TRUE(v->type->Is<ast::I32>());
+  EXPECT_EQ(v->source.range.begin.line, 0u);
+  EXPECT_EQ(v->source.range.begin.column, 0u);
+  EXPECT_EQ(v->source.range.end.line, 0u);
+  EXPECT_EQ(v->source.range.end.column, 0u);
 }
 
 TEST_F(VariableTest, CreationWithSource) {
@@ -39,13 +39,13 @@
       Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 5}}},
       "i", ty.f32(), StorageClass::kPrivate, nullptr, DecorationList{});
 
-  EXPECT_EQ(v->symbol(), Symbol(1, ID()));
-  EXPECT_EQ(v->declared_storage_class(), StorageClass::kPrivate);
-  EXPECT_TRUE(v->type()->Is<ast::F32>());
-  EXPECT_EQ(v->source().range.begin.line, 27u);
-  EXPECT_EQ(v->source().range.begin.column, 4u);
-  EXPECT_EQ(v->source().range.end.line, 27u);
-  EXPECT_EQ(v->source().range.end.column, 5u);
+  EXPECT_EQ(v->symbol, Symbol(1, ID()));
+  EXPECT_EQ(v->declared_storage_class, StorageClass::kPrivate);
+  EXPECT_TRUE(v->type->Is<ast::F32>());
+  EXPECT_EQ(v->source.range.begin.line, 27u);
+  EXPECT_EQ(v->source.range.begin.column, 4u);
+  EXPECT_EQ(v->source.range.end.line, 27u);
+  EXPECT_EQ(v->source.range.end.column, 5u);
 }
 
 TEST_F(VariableTest, CreationEmpty) {
@@ -53,13 +53,13 @@
       Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 7}}},
       "a_var", ty.i32(), StorageClass::kWorkgroup, nullptr, DecorationList{});
 
-  EXPECT_EQ(v->symbol(), Symbol(1, ID()));
-  EXPECT_EQ(v->declared_storage_class(), StorageClass::kWorkgroup);
-  EXPECT_TRUE(v->type()->Is<ast::I32>());
-  EXPECT_EQ(v->source().range.begin.line, 27u);
-  EXPECT_EQ(v->source().range.begin.column, 4u);
-  EXPECT_EQ(v->source().range.end.line, 27u);
-  EXPECT_EQ(v->source().range.end.column, 7u);
+  EXPECT_EQ(v->symbol, Symbol(1, ID()));
+  EXPECT_EQ(v->declared_storage_class, StorageClass::kWorkgroup);
+  EXPECT_TRUE(v->type->Is<ast::I32>());
+  EXPECT_EQ(v->source.range.begin.line, 27u);
+  EXPECT_EQ(v->source.range.begin.column, 4u);
+  EXPECT_EQ(v->source.range.end.line, 27u);
+  EXPECT_EQ(v->source.range.end.column, 7u);
 }
 
 TEST_F(VariableTest, Assert_MissingSymbol) {
@@ -99,14 +99,14 @@
                       create<OverrideDecoration>(1200),
                   });
 
-  auto& decorations = var->decorations();
+  auto& decorations = var->decorations;
   EXPECT_TRUE(ast::HasDecoration<ast::LocationDecoration>(decorations));
   EXPECT_TRUE(ast::HasDecoration<ast::BuiltinDecoration>(decorations));
   EXPECT_TRUE(ast::HasDecoration<ast::OverrideDecoration>(decorations));
 
   auto* location = ast::GetDecoration<ast::LocationDecoration>(decorations);
   ASSERT_NE(nullptr, location);
-  EXPECT_EQ(1u, location->value());
+  EXPECT_EQ(1u, location->value);
 }
 
 TEST_F(VariableTest, BindingPoint) {
@@ -115,19 +115,19 @@
                       create<BindingDecoration>(2),
                       create<GroupDecoration>(1),
                   });
-  EXPECT_TRUE(var->binding_point());
-  ASSERT_NE(var->binding_point().binding, nullptr);
-  ASSERT_NE(var->binding_point().group, nullptr);
-  EXPECT_EQ(var->binding_point().binding->value(), 2u);
-  EXPECT_EQ(var->binding_point().group->value(), 1u);
+  EXPECT_TRUE(var->BindingPoint());
+  ASSERT_NE(var->BindingPoint().binding, nullptr);
+  ASSERT_NE(var->BindingPoint().group, nullptr);
+  EXPECT_EQ(var->BindingPoint().binding->value, 2u);
+  EXPECT_EQ(var->BindingPoint().group->value, 1u);
 }
 
 TEST_F(VariableTest, BindingPointoDecorations) {
   auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
                   DecorationList{});
-  EXPECT_FALSE(var->binding_point());
-  EXPECT_EQ(var->binding_point().group, nullptr);
-  EXPECT_EQ(var->binding_point().binding, nullptr);
+  EXPECT_FALSE(var->BindingPoint());
+  EXPECT_EQ(var->BindingPoint().group, nullptr);
+  EXPECT_EQ(var->BindingPoint().binding, nullptr);
 }
 
 TEST_F(VariableTest, BindingPointMissingGroupDecoration) {
@@ -135,19 +135,19 @@
                   DecorationList{
                       create<BindingDecoration>(2),
                   });
-  EXPECT_FALSE(var->binding_point());
-  ASSERT_NE(var->binding_point().binding, nullptr);
-  EXPECT_EQ(var->binding_point().binding->value(), 2u);
-  EXPECT_EQ(var->binding_point().group, nullptr);
+  EXPECT_FALSE(var->BindingPoint());
+  ASSERT_NE(var->BindingPoint().binding, nullptr);
+  EXPECT_EQ(var->BindingPoint().binding->value, 2u);
+  EXPECT_EQ(var->BindingPoint().group, nullptr);
 }
 
 TEST_F(VariableTest, BindingPointMissingBindingDecoration) {
   auto* var = Var("my_var", ty.i32(), StorageClass::kFunction, nullptr,
                   DecorationList{create<GroupDecoration>(1)});
-  EXPECT_FALSE(var->binding_point());
-  ASSERT_NE(var->binding_point().group, nullptr);
-  EXPECT_EQ(var->binding_point().group->value(), 1u);
-  EXPECT_EQ(var->binding_point().binding, nullptr);
+  EXPECT_FALSE(var->BindingPoint());
+  ASSERT_NE(var->BindingPoint().group, nullptr);
+  EXPECT_EQ(var->BindingPoint().group->value, 1u);
+  EXPECT_EQ(var->BindingPoint().binding, nullptr);
 }
 
 }  // namespace
diff --git a/src/ast/vector.cc b/src/ast/vector.cc
index b3d6d89..4fdd60e 100644
--- a/src/ast/vector.cc
+++ b/src/ast/vector.cc
@@ -21,14 +21,14 @@
 namespace tint {
 namespace ast {
 
-Vector::Vector(ProgramID program_id,
-               const Source& source,
+Vector::Vector(ProgramID pid,
+               const Source& src,
                Type const* subtype,
-               uint32_t size)
-    : Base(program_id, source), subtype_(subtype), size_(size) {
+               uint32_t w)
+    : Base(pid, src), type(const_cast<Type*>(subtype)), width(w) {
   TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, subtype, program_id);
-  TINT_ASSERT(AST, size_ > 1);
-  TINT_ASSERT(AST, size_ < 5);
+  TINT_ASSERT(AST, width > 1);
+  TINT_ASSERT(AST, width < 5);
 }
 
 Vector::Vector(Vector&&) = default;
@@ -37,15 +37,15 @@
 
 std::string Vector::FriendlyName(const SymbolTable& symbols) const {
   std::ostringstream out;
-  out << "vec" << size_ << "<" << subtype_->FriendlyName(symbols) << ">";
+  out << "vec" << width << "<" << type->FriendlyName(symbols) << ">";
   return out.str();
 }
 
 Vector* Vector::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* ty = ctx->Clone(type());
-  return ctx->dst->create<Vector>(src, ty, size_);
+  auto src = ctx->Clone(source);
+  auto* ty = ctx->Clone(type);
+  return ctx->dst->create<Vector>(src, ty, width);
 }
 
 }  // namespace ast
diff --git a/src/ast/vector.h b/src/ast/vector.h
index 9a6f402..91a53c5 100644
--- a/src/ast/vector.h
+++ b/src/ast/vector.h
@@ -26,23 +26,15 @@
 class Vector : public Castable<Vector, Type> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param subtype the vector element type
-  /// @param size the number of elements in the vector
-  Vector(ProgramID program_id,
-         const Source& source,
-         Type const* subtype,
-         uint32_t size);
+  /// @param width the number of elements in the vector
+  Vector(ProgramID pid, const Source& src, Type const* subtype, uint32_t width);
   /// Move constructor
   Vector(Vector&&);
   ~Vector() override;
 
-  /// @returns the type of the vector elements
-  Type* type() const { return const_cast<Type*>(subtype_); }
-  /// @returns the size of the vector
-  uint32_t size() const { return size_; }
-
   /// @param symbols the program's symbol table
   /// @returns the name for this type that closely resembles how it would be
   /// declared in WGSL.
@@ -53,9 +45,11 @@
   /// @return the newly cloned type
   Vector* Clone(CloneContext* ctx) const override;
 
- private:
-  Type const* const subtype_;
-  uint32_t const size_;
+  /// The type of the vector elements
+  Type* const type;
+
+  /// The number of elements in the vector
+  uint32_t const width;
 };
 
 }  // namespace ast
diff --git a/src/ast/vector_test.cc b/src/ast/vector_test.cc
index 4cbbc71..87cff03 100644
--- a/src/ast/vector_test.cc
+++ b/src/ast/vector_test.cc
@@ -26,8 +26,8 @@
 TEST_F(AstVectorTest, Creation) {
   auto* i32 = create<I32>();
   auto* v = create<Vector>(i32, 2);
-  EXPECT_EQ(v->type(), i32);
-  EXPECT_EQ(v->size(), 2u);
+  EXPECT_EQ(v->type, i32);
+  EXPECT_EQ(v->width, 2u);
 }
 
 TEST_F(AstVectorTest, FriendlyName) {
diff --git a/src/ast/void.cc b/src/ast/void.cc
index a96d5f0..427d827 100644
--- a/src/ast/void.cc
+++ b/src/ast/void.cc
@@ -21,8 +21,7 @@
 namespace tint {
 namespace ast {
 
-Void::Void(ProgramID program_id, const Source& source)
-    : Base(program_id, source) {}
+Void::Void(ProgramID pid, const Source& src) : Base(pid, src) {}
 
 Void::Void(Void&&) = default;
 
@@ -33,7 +32,7 @@
 }
 
 Void* Void::Clone(CloneContext* ctx) const {
-  auto src = ctx->Clone(source());
+  auto src = ctx->Clone(source);
   return ctx->dst->create<Void>(src);
 }
 
diff --git a/src/ast/void.h b/src/ast/void.h
index 94e0fda..46cb3a2 100644
--- a/src/ast/void.h
+++ b/src/ast/void.h
@@ -26,9 +26,9 @@
 class Void : public Castable<Void, Type> {
  public:
   /// Constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this node
-  Void(ProgramID program_id, const Source& source);
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
+  Void(ProgramID pid, const Source& src);
   /// Move constructor
   Void(Void&&);
   ~Void() override;
diff --git a/src/ast/workgroup_decoration.cc b/src/ast/workgroup_decoration.cc
index 9b346aa..271bb85 100644
--- a/src/ast/workgroup_decoration.cc
+++ b/src/ast/workgroup_decoration.cc
@@ -23,26 +23,26 @@
 namespace tint {
 namespace ast {
 
-WorkgroupDecoration::WorkgroupDecoration(ProgramID program_id,
-                                         const Source& source,
-                                         ast::Expression* x,
-                                         ast::Expression* y,
-                                         ast::Expression* z)
-    : Base(program_id, source), x_(x), y_(y), z_(z) {}
+WorkgroupDecoration::WorkgroupDecoration(ProgramID pid,
+                                         const Source& src,
+                                         ast::Expression* x_,
+                                         ast::Expression* y_,
+                                         ast::Expression* z_)
+    : Base(pid, src), x(x_), y(y_), z(z_) {}
 
 WorkgroupDecoration::~WorkgroupDecoration() = default;
 
-std::string WorkgroupDecoration::name() const {
+std::string WorkgroupDecoration::Name() const {
   return "workgroup_size";
 }
 
 WorkgroupDecoration* WorkgroupDecoration::Clone(CloneContext* ctx) const {
   // Clone arguments outside of create() call to have deterministic ordering
-  auto src = ctx->Clone(source());
-  auto* x = ctx->Clone(x_);
-  auto* y = ctx->Clone(y_);
-  auto* z = ctx->Clone(z_);
-  return ctx->dst->create<WorkgroupDecoration>(src, x, y, z);
+  auto src = ctx->Clone(source);
+  auto* x_ = ctx->Clone(x);
+  auto* y_ = ctx->Clone(y);
+  auto* z_ = ctx->Clone(z);
+  return ctx->dst->create<WorkgroupDecoration>(src, x_, y_, z_);
 }
 
 }  // namespace ast
diff --git a/src/ast/workgroup_decoration.h b/src/ast/workgroup_decoration.h
index f9d8e56..daae3f0 100644
--- a/src/ast/workgroup_decoration.h
+++ b/src/ast/workgroup_decoration.h
@@ -30,13 +30,13 @@
 class WorkgroupDecoration : public Castable<WorkgroupDecoration, Decoration> {
  public:
   /// constructor
-  /// @param program_id the identifier of the program that owns this node
-  /// @param source the source of this decoration
+  /// @param pid the identifier of the program that owns this node
+  /// @param src the source of this node
   /// @param x the workgroup x dimension expression
   /// @param y the optional workgroup y dimension expression
   /// @param z the optional workgroup z dimension expression
-  WorkgroupDecoration(ProgramID program_id,
-                      const Source& source,
+  WorkgroupDecoration(ProgramID pid,
+                      const Source& src,
                       ast::Expression* x,
                       ast::Expression* y = nullptr,
                       ast::Expression* z = nullptr);
@@ -44,10 +44,10 @@
   ~WorkgroupDecoration() override;
 
   /// @returns the workgroup dimensions
-  std::array<ast::Expression*, 3> values() const { return {x_, y_, z_}; }
+  std::array<ast::Expression*, 3> Values() const { return {x, y, z}; }
 
   /// @returns the WGSL name for the decoration
-  std::string name() const override;
+  std::string Name() const override;
 
   /// Clones this node and all transitive child nodes using the `CloneContext`
   /// `ctx`.
@@ -55,10 +55,12 @@
   /// @return the newly cloned node
   WorkgroupDecoration* Clone(CloneContext* ctx) const override;
 
- private:
-  ast::Expression* const x_ = nullptr;
-  ast::Expression* const y_ = nullptr;
-  ast::Expression* const z_ = nullptr;
+  /// The workgroup x dimension.
+  ast::Expression* const x;
+  /// The optional workgroup y dimension. May be null.
+  ast::Expression* const y = nullptr;
+  /// The optional workgroup z dimension. May be null.
+  ast::Expression* const z = nullptr;
 };
 
 }  // namespace ast
diff --git a/src/ast/workgroup_decoration_test.cc b/src/ast/workgroup_decoration_test.cc
index f437c63..cbf7ee8 100644
--- a/src/ast/workgroup_decoration_test.cc
+++ b/src/ast/workgroup_decoration_test.cc
@@ -25,75 +25,75 @@
 
 TEST_F(WorkgroupDecorationTest, Creation_1param) {
   auto* d = WorkgroupSize(2);
-  auto values = d->values();
+  auto values = d->Values();
   ASSERT_NE(values[0], nullptr);
   auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
   ASSERT_TRUE(x_scalar);
-  ASSERT_TRUE(x_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(x_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 2u);
+  ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
 
   EXPECT_EQ(values[1], nullptr);
   EXPECT_EQ(values[2], nullptr);
 }
 TEST_F(WorkgroupDecorationTest, Creation_2param) {
   auto* d = WorkgroupSize(2, 4);
-  auto values = d->values();
+  auto values = d->Values();
   ASSERT_NE(values[0], nullptr);
   auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
   ASSERT_TRUE(x_scalar);
-  ASSERT_TRUE(x_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(x_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 2u);
+  ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
 
   ASSERT_NE(values[1], nullptr);
   auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>();
   ASSERT_TRUE(y_scalar);
-  ASSERT_TRUE(y_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(y_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 4u);
+  ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
 
   EXPECT_EQ(values[2], nullptr);
 }
 
 TEST_F(WorkgroupDecorationTest, Creation_3param) {
   auto* d = WorkgroupSize(2, 4, 6);
-  auto values = d->values();
+  auto values = d->Values();
   ASSERT_NE(values[0], nullptr);
   auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
   ASSERT_TRUE(x_scalar);
-  ASSERT_TRUE(x_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(x_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 2u);
+  ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
 
   ASSERT_NE(values[1], nullptr);
   auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>();
   ASSERT_TRUE(y_scalar);
-  ASSERT_TRUE(y_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(y_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 4u);
+  ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
 
   ASSERT_NE(values[2], nullptr);
   auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>();
   ASSERT_TRUE(z_scalar);
-  ASSERT_TRUE(z_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(z_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 6u);
+  ASSERT_TRUE(z_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(z_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 6u);
 }
 
 TEST_F(WorkgroupDecorationTest, Creation_WithIdentifier) {
   auto* d = WorkgroupSize(2, 4, "depth");
-  auto values = d->values();
+  auto values = d->Values();
   ASSERT_NE(values[0], nullptr);
   auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
   ASSERT_TRUE(x_scalar);
-  ASSERT_TRUE(x_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(x_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 2u);
+  ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
 
   ASSERT_NE(values[1], nullptr);
   auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>();
   ASSERT_TRUE(y_scalar);
-  ASSERT_TRUE(y_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(y_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 4u);
+  ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
 
   ASSERT_NE(values[2], nullptr);
   auto* z_ident = values[2]->As<ast::IdentifierExpression>();
   ASSERT_TRUE(z_ident);
-  EXPECT_EQ(Symbols().NameFor(z_ident->symbol()), "depth");
+  EXPECT_EQ(Symbols().NameFor(z_ident->symbol), "depth");
 }
 
 }  // namespace
diff --git a/src/clone_context.h b/src/clone_context.h
index 4f72d2f..04f5dac 100644
--- a/src/clone_context.h
+++ b/src/clone_context.h
@@ -255,8 +255,8 @@
   ///   CloneCtx ctx(&out, in);
   ///   ctx.ReplaceAll([&] (ast::UintLiteral* l) {
   ///       return ctx->dst->create<ast::UintLiteral>(
-  ///           ctx->Clone(l->source()),
-  ///           ctx->Clone(l->type()),
+  ///           ctx->Clone(l->source),
+  ///           ctx->Clone(l->type),
   ///           42);
   ///     });
   ///   ctx.Clone();
diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc
index d4fa744..fe64df1 100644
--- a/src/inspector/inspector.cc
+++ b/src/inspector/inspector.cc
@@ -114,8 +114,8 @@
     return {InterpolationType::kPerspective, InterpolationSampling::kCenter};
   }
 
-  auto interpolation_type = interpolation_decoration->type();
-  auto sampling = interpolation_decoration->sampling();
+  auto interpolation_type = interpolation_decoration->type;
+  auto sampling = interpolation_decoration->sampling;
   if (interpolation_type != ast::InterpolationType::kFlat &&
       sampling == ast::InterpolationSampling::kNone) {
     sampling = ast::InterpolationSampling::kCenter;
@@ -141,9 +141,9 @@
     auto* sem = program_->Sem().Get(func);
 
     EntryPoint entry_point;
-    entry_point.name = program_->Symbols().NameFor(func->symbol());
-    entry_point.remapped_name = program_->Symbols().NameFor(func->symbol());
-    entry_point.stage = func->pipeline_stage();
+    entry_point.name = program_->Symbols().NameFor(func->symbol);
+    entry_point.remapped_name = program_->Symbols().NameFor(func->symbol);
+    entry_point.stage = func->PipelineStage();
 
     auto wgsize = sem->workgroup_size();
     entry_point.workgroup_size_x = wgsize[0].value;
@@ -157,41 +157,41 @@
 
     for (auto* param : sem->Parameters()) {
       AddEntryPointInOutVariables(
-          program_->Symbols().NameFor(param->Declaration()->symbol()),
-          param->Type(), param->Declaration()->decorations(),
+          program_->Symbols().NameFor(param->Declaration()->symbol),
+          param->Type(), param->Declaration()->decorations,
           entry_point.input_variables);
 
       entry_point.input_position_used |=
           ContainsBuiltin(ast::Builtin::kPosition, param->Type(),
-                          param->Declaration()->decorations());
+                          param->Declaration()->decorations);
       entry_point.front_facing_used |=
           ContainsBuiltin(ast::Builtin::kFrontFacing, param->Type(),
-                          param->Declaration()->decorations());
+                          param->Declaration()->decorations);
       entry_point.sample_index_used |=
           ContainsBuiltin(ast::Builtin::kSampleIndex, param->Type(),
-                          param->Declaration()->decorations());
+                          param->Declaration()->decorations);
       entry_point.input_sample_mask_used |=
           ContainsBuiltin(ast::Builtin::kSampleMask, param->Type(),
-                          param->Declaration()->decorations());
+                          param->Declaration()->decorations);
       entry_point.num_workgroups_used |=
           ContainsBuiltin(ast::Builtin::kNumWorkgroups, param->Type(),
-                          param->Declaration()->decorations());
+                          param->Declaration()->decorations);
     }
 
     if (!sem->ReturnType()->Is<sem::Void>()) {
       AddEntryPointInOutVariables("<retval>", sem->ReturnType(),
-                                  func->return_type_decorations(),
+                                  func->return_type_decorations,
                                   entry_point.output_variables);
 
       entry_point.output_sample_mask_used =
           ContainsBuiltin(ast::Builtin::kSampleMask, sem->ReturnType(),
-                          func->return_type_decorations());
+                          func->return_type_decorations);
     }
 
     for (auto* var : sem->ReferencedModuleVariables()) {
       auto* decl = var->Declaration();
 
-      auto name = program_->Symbols().NameFor(decl->symbol());
+      auto name = program_->Symbols().NameFor(decl->symbol);
 
       auto* global = var->As<sem::GlobalVariable>();
       if (global && global->IsPipelineConstant()) {
@@ -212,7 +212,7 @@
         }
 
         overridable_constant.is_initialized =
-            global->Declaration()->has_constructor();
+            global->Declaration()->constructor;
 
         entry_point.overridable_constants.push_back(overridable_constant);
       }
@@ -254,12 +254,12 @@
       continue;
     }
 
-    if (!var->has_constructor()) {
+    if (!var->constructor) {
       result[constant_id] = Scalar();
       continue;
     }
 
-    auto* expression = var->constructor();
+    auto* expression = var->constructor;
     auto* constructor = expression->As<ast::ConstructorExpression>();
     if (constructor == nullptr) {
       // This is invalid WGSL, but handling gracefully.
@@ -275,7 +275,7 @@
       continue;
     }
 
-    auto* literal = scalar_constructor->literal();
+    auto* literal = scalar_constructor->literal;
     if (!literal) {
       // This is invalid WGSL, but handling gracefully.
       result[constant_id] = Scalar();
@@ -283,22 +283,22 @@
     }
 
     if (auto* l = literal->As<ast::BoolLiteral>()) {
-      result[constant_id] = Scalar(l->IsTrue());
+      result[constant_id] = Scalar(l->value);
       continue;
     }
 
     if (auto* l = literal->As<ast::UintLiteral>()) {
-      result[constant_id] = Scalar(l->value());
+      result[constant_id] = Scalar(l->value);
       continue;
     }
 
     if (auto* l = literal->As<ast::SintLiteral>()) {
-      result[constant_id] = Scalar(l->value());
+      result[constant_id] = Scalar(l->value);
       continue;
     }
 
     if (auto* l = literal->As<ast::FloatLiteral>()) {
-      result[constant_id] = Scalar(l->value());
+      result[constant_id] = Scalar(l->value);
       continue;
     }
 
@@ -313,7 +313,7 @@
   for (auto* var : program_->AST().GlobalVariables()) {
     auto* global = program_->Sem().Get<sem::GlobalVariable>(var);
     if (global && global->IsPipelineConstant()) {
-      auto name = program_->Symbols().NameFor(var->symbol());
+      auto name = program_->Symbols().NameFor(var->symbol);
       result[name] = global->ConstantId();
     }
   }
@@ -400,8 +400,8 @@
 
     ResourceBinding entry;
     entry.resource_type = ResourceBinding::ResourceType::kUniformBuffer;
-    entry.bind_group = binding_info.group->value();
-    entry.binding = binding_info.binding->value();
+    entry.bind_group = binding_info.group->value;
+    entry.binding = binding_info.binding->value;
     entry.size = str->Size();
     entry.size_no_padding = str->SizeNoPadding();
 
@@ -437,8 +437,8 @@
 
     ResourceBinding entry;
     entry.resource_type = ResourceBinding::ResourceType::kSampler;
-    entry.bind_group = binding_info.group->value();
-    entry.binding = binding_info.binding->value();
+    entry.bind_group = binding_info.group->value;
+    entry.binding = binding_info.binding->value;
 
     result.push_back(entry);
   }
@@ -461,8 +461,8 @@
 
     ResourceBinding entry;
     entry.resource_type = ResourceBinding::ResourceType::kComparisonSampler;
-    entry.bind_group = binding_info.group->value();
-    entry.binding = binding_info.binding->value();
+    entry.bind_group = binding_info.group->value;
+    entry.binding = binding_info.binding->value;
 
     result.push_back(entry);
   }
@@ -503,8 +503,8 @@
 
     ResourceBinding entry;
     entry.resource_type = resource_type;
-    entry.bind_group = binding_info.group->value();
-    entry.binding = binding_info.binding->value();
+    entry.bind_group = binding_info.group->value;
+    entry.binding = binding_info.binding->value;
 
     auto* tex = var->Type()->UnwrapRef()->As<sem::Texture>();
     entry.dim =
@@ -612,8 +612,8 @@
     for (auto* member : struct_ty->Members()) {
       AddEntryPointInOutVariables(
           name + "." +
-              program_->Symbols().NameFor(member->Declaration()->symbol()),
-          member->Type(), member->Declaration()->decorations(), variables);
+              program_->Symbols().NameFor(member->Declaration()->symbol),
+          member->Type(), member->Declaration()->decorations, variables);
     }
     return;
   }
@@ -628,7 +628,7 @@
   auto* location = ast::GetDecoration<ast::LocationDecoration>(decorations);
   TINT_ASSERT(Inspector, location != nullptr);
   stage_variable.has_location_decoration = true;
-  stage_variable.location_decoration = location->value();
+  stage_variable.location_decoration = location->value;
 
   std::tie(stage_variable.interpolation_type,
            stage_variable.interpolation_sampling) =
@@ -646,7 +646,7 @@
     // Recurse into members.
     for (auto* member : struct_ty->Members()) {
       if (ContainsBuiltin(builtin, member->Type(),
-                          member->Declaration()->decorations())) {
+                          member->Declaration()->decorations)) {
         return true;
       }
     }
@@ -656,7 +656,7 @@
   // Base case: check for builtin
   auto* builtin_declaration =
       ast::GetDecoration<ast::BuiltinDecoration>(decorations);
-  if (!builtin_declaration || builtin_declaration->value() != builtin) {
+  if (!builtin_declaration || builtin_declaration->builtin != builtin) {
     return false;
   }
 
@@ -690,8 +690,8 @@
     entry.resource_type =
         read_only ? ResourceBinding::ResourceType::kReadOnlyStorageBuffer
                   : ResourceBinding::ResourceType::kStorageBuffer;
-    entry.bind_group = binding_info.group->value();
-    entry.binding = binding_info.binding->value();
+    entry.bind_group = binding_info.group->value;
+    entry.binding = binding_info.binding->value;
     entry.size = str->Size();
     entry.size_no_padding = str->SizeNoPadding();
 
@@ -722,8 +722,8 @@
     entry.resource_type =
         multisampled_only ? ResourceBinding::ResourceType::kMultisampledTexture
                           : ResourceBinding::ResourceType::kSampledTexture;
-    entry.bind_group = binding_info.group->value();
-    entry.binding = binding_info.binding->value();
+    entry.bind_group = binding_info.group->value;
+    entry.binding = binding_info.binding->value;
 
     auto* texture_type = var->Type()->UnwrapRef()->As<sem::Texture>();
     entry.dim = TypeTextureDimensionToResourceBindingTextureDimension(
@@ -761,8 +761,8 @@
     ResourceBinding entry;
     entry.resource_type =
         ResourceBinding::ResourceType::kWriteOnlyStorageTexture;
-    entry.bind_group = binding_info.group->value();
-    entry.binding = binding_info.binding->value();
+    entry.bind_group = binding_info.group->value;
+    entry.binding = binding_info.binding->value;
 
     entry.dim = TypeTextureDimensionToResourceBindingTextureDimension(
         texture_type->dim());
@@ -820,7 +820,7 @@
     auto* call_func = call->Stmt()->Function();
     std::vector<Symbol> entry_points;
     if (call_func->IsEntryPoint()) {
-      entry_points = {call_func->symbol()};
+      entry_points = {call_func->symbol};
     } else {
       entry_points = sem.Get(call_func)->AncestorEntryPoints();
     }
@@ -829,21 +829,21 @@
       continue;
     }
 
-    auto* t = c->args()[texture_index];
-    auto* s = c->args()[sampler_index];
+    auto* t = c->args[texture_index];
+    auto* s = c->args[sampler_index];
 
     GetOriginatingResources(
         std::array<const ast::Expression*, 2>{t, s},
         [&](std::array<const sem::GlobalVariable*, 2> globals) {
           auto* texture = globals[0];
           sem::BindingPoint texture_binding_point = {
-              texture->Declaration()->binding_point().group->value(),
-              texture->Declaration()->binding_point().binding->value()};
+              texture->Declaration()->BindingPoint().group->value,
+              texture->Declaration()->BindingPoint().binding->value};
 
           auto* sampler = globals[1];
           sem::BindingPoint sampler_binding_point = {
-              sampler->Declaration()->binding_point().group->value(),
-              sampler->Declaration()->binding_point().binding->value()};
+              sampler->Declaration()->BindingPoint().group->value,
+              sampler->Declaration()->BindingPoint().binding->value};
 
           for (auto entry_point : entry_points) {
             const auto& ep_name = program_->Symbols().NameFor(entry_point);
@@ -885,7 +885,7 @@
 
         if (auto* local = tint::As<sem::LocalVariable>(var)) {
           // Chase the variable
-          expr = local->Declaration()->constructor();
+          expr = local->Declaration()->constructor;
           if (!expr) {
             TINT_ICE(Inspector, diagnostics_)
                 << "resource variable had no initializer";
@@ -916,17 +916,17 @@
       }
 
       if (auto* unary = tint::As<ast::UnaryOpExpression>(expr)) {
-        switch (unary->op()) {
+        switch (unary->op) {
           case ast::UnaryOp::kAddressOf:
           case ast::UnaryOp::kIndirection:
             // `*` and `&` are the only valid unary ops for a resource type,
             // and must be balanced in order for the program to have passed
             // validation. Just skip past these.
-            expr = unary->expr();
+            expr = unary->expr;
             continue;
           default: {
             TINT_ICE(Inspector, diagnostics_)
-                << "unexpected unary op on resource: " << unary->op();
+                << "unexpected unary op on resource: " << unary->op;
             return;
           }
         }
@@ -946,7 +946,7 @@
       // Patch all the parameter expressions with their argument
       for (size_t i = 0; i < N; i++) {
         if (auto* param = parameters[i]) {
-          call_exprs[i] = call_expr->args()[param->Index()];
+          call_exprs[i] = call_expr->args[param->Index()];
         }
       }
       // Now call GetOriginatingResources() with from the callsite
diff --git a/src/program_builder.cc b/src/program_builder.cc
index 287175c..f9b6bc6 100644
--- a/src/program_builder.cc
+++ b/src/program_builder.cc
@@ -65,7 +65,7 @@
   builder.id_ = program->ID();
   builder.types_ = sem::Manager::Wrap(program->Types());
   builder.ast_ = builder.create<ast::Module>(
-      program->AST().source(), program->AST().GlobalDeclarations());
+      program->AST().source, program->AST().GlobalDeclarations());
   builder.sem_ = sem::Info::Wrap(program->Sem());
   builder.symbols_ = program->Symbols();
   builder.diagnostics_ = program->Diagnostics();
@@ -108,12 +108,12 @@
 }
 
 ast::TypeName* ProgramBuilder::TypesBuilder::Of(ast::TypeDecl* decl) const {
-  return type_name(decl->name());
+  return type_name(decl->name);
 }
 
 const ast::TypeName* ProgramBuilder::TypesBuilder::Of(
     const ast::TypeDecl* decl) const {
-  return type_name(decl->name());
+  return type_name(decl->name);
 }
 
 ProgramBuilder::TypesBuilder::TypesBuilder(ProgramBuilder* pb) : builder(pb) {}
diff --git a/src/program_builder.h b/src/program_builder.h
index bc529e8..39a1fa3 100644
--- a/src/program_builder.h
+++ b/src/program_builder.h
@@ -965,13 +965,13 @@
   /// @return an ast::IdentifierExpression with the variable's symbol
   ast::IdentifierExpression* Expr(const Source& source,
                                   ast::Variable* variable) {
-    return create<ast::IdentifierExpression>(source, variable->symbol());
+    return create<ast::IdentifierExpression>(source, variable->symbol);
   }
 
   /// @param variable the AST variable
   /// @return an ast::IdentifierExpression with the variable's symbol
   ast::IdentifierExpression* Expr(ast::Variable* variable) {
-    return create<ast::IdentifierExpression>(variable->symbol());
+    return create<ast::IdentifierExpression>(variable->symbol);
   }
 
   /// @param source the source information
diff --git a/src/program_builder_test.cc b/src/program_builder_test.cc
index bfa9159..5367cdd 100644
--- a/src/program_builder_test.cc
+++ b/src/program_builder_test.cc
@@ -60,7 +60,7 @@
   ASSERT_EQ(inner.AST().Functions().size(), 1u);
   ASSERT_EQ(outer.AST().Functions().size(), 2u);
   EXPECT_EQ(inner.AST().Functions()[0], outer.AST().Functions()[0]);
-  EXPECT_EQ(outer.AST().Functions()[1]->symbol(), outer.Symbols().Get("b"));
+  EXPECT_EQ(outer.AST().Functions()[1]->symbol, outer.Symbols().Get("b"));
   EXPECT_EQ(inner.Symbols().Get("a"), outer.Symbols().Get("a"));
   EXPECT_TRUE(inner.Symbols().Get("a").IsValid());
   EXPECT_TRUE(outer.Symbols().Get("a").IsValid());
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 07d904f..b9ef0c9 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -703,7 +703,7 @@
 /// @returns true if the decorations include a SampleMask builtin
 bool HasBuiltinSampleMask(const ast::DecorationList& decos) {
   if (auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(decos)) {
-    return builtin->value() == ast::Builtin::kSampleMask;
+    return builtin->builtin == ast::Builtin::kSampleMask;
   }
   return false;
 }
@@ -1061,7 +1061,7 @@
       // Replace this location decoration with a new one with one higher index.
       // The old one doesn't leak because it's kept in the builder's AST node
       // list.
-      deco = builder_.Location(loc_deco->source(), loc_deco->value() + 1);
+      deco = builder_.Location(loc_deco->source, loc_deco->value + 1);
     }
   }
 }
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index ae37f47..8961756 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -1200,7 +1200,7 @@
   auto* ast_struct = create<ast::Struct>(Source{}, sym, std::move(ast_members),
                                          std::move(ast_struct_decorations));
   if (num_non_writable_members == members.size()) {
-    read_only_struct_types_.insert(ast_struct->name());
+    read_only_struct_types_.insert(ast_struct->name);
   }
   AddTypeDecl(sym, ast_struct);
   const auto* result = ty_.Struct(sym, std::move(ast_member_types));
diff --git a/src/reader/spirv/parser_impl_barrier_test.cc b/src/reader/spirv/parser_impl_barrier_test.cc
index 1e64306..da4df49 100644
--- a/src/reader/spirv/parser_impl_barrier_test.cc
+++ b/src/reader/spirv/parser_impl_barrier_test.cc
@@ -68,11 +68,11 @@
   auto* helper =
       program.AST().Functions().Find(program.Symbols().Get("helper"));
   ASSERT_NE(helper, nullptr);
-  ASSERT_GT(helper->body()->size(), 0u);
-  auto* call = helper->body()->get(0)->As<ast::CallStatement>();
+  ASSERT_GT(helper->body->statements.size(), 0u);
+  auto* call = helper->body->statements[0]->As<ast::CallStatement>();
   ASSERT_NE(call, nullptr);
-  EXPECT_EQ(call->expr()->args().size(), 0u);
-  auto* sem_call = program.Sem().Get(call->expr());
+  EXPECT_EQ(call->expr->args.size(), 0u);
+  auto* sem_call = program.Sem().Get(call->expr);
   ASSERT_NE(sem_call, nullptr);
   auto* intrinsic = sem_call->Target()->As<sem::Intrinsic>();
   ASSERT_NE(intrinsic, nullptr);
@@ -102,11 +102,11 @@
   auto* helper =
       program.AST().Functions().Find(program.Symbols().Get("helper"));
   ASSERT_NE(helper, nullptr);
-  ASSERT_GT(helper->body()->size(), 0u);
-  auto* call = helper->body()->get(0)->As<ast::CallStatement>();
+  ASSERT_GT(helper->body->statements.size(), 0u);
+  auto* call = helper->body->statements[0]->As<ast::CallStatement>();
   ASSERT_NE(call, nullptr);
-  EXPECT_EQ(call->expr()->args().size(), 0u);
-  auto* sem_call = program.Sem().Get(call->expr());
+  EXPECT_EQ(call->expr->args.size(), 0u);
+  auto* sem_call = program.Sem().Get(call->expr);
   ASSERT_NE(sem_call, nullptr);
   auto* intrinsic = sem_call->Target()->As<sem::Intrinsic>();
   ASSERT_NE(intrinsic, nullptr);
diff --git a/src/reader/spirv/parser_impl_convert_member_decoration_test.cc b/src/reader/spirv/parser_impl_convert_member_decoration_test.cc
index d431fb5..ae5ebe3 100644
--- a/src/reader/spirv/parser_impl_convert_member_decoration_test.cc
+++ b/src/reader/spirv/parser_impl_convert_member_decoration_test.cc
@@ -59,7 +59,7 @@
   EXPECT_TRUE(result[0]->Is<ast::StructMemberOffsetDecoration>());
   auto* offset_deco = result[0]->As<ast::StructMemberOffsetDecoration>();
   ASSERT_NE(offset_deco, nullptr);
-  EXPECT_EQ(offset_deco->offset(), 8u);
+  EXPECT_EQ(offset_deco->offset, 8u);
   EXPECT_TRUE(p->error().empty());
 }
 
@@ -85,7 +85,7 @@
   EXPECT_TRUE(result[0]->Is<ast::StrideDecoration>());
   auto* stride_deco = result[0]->As<ast::StrideDecoration>();
   ASSERT_NE(stride_deco, nullptr);
-  EXPECT_EQ(stride_deco->stride(), 16u);
+  EXPECT_EQ(stride_deco->stride, 16u);
   EXPECT_TRUE(p->error().empty());
 }
 
@@ -111,7 +111,7 @@
   EXPECT_TRUE(result[0]->Is<ast::StrideDecoration>());
   auto* stride_deco = result[0]->As<ast::StrideDecoration>();
   ASSERT_NE(stride_deco, nullptr);
-  EXPECT_EQ(stride_deco->stride(), 64u);
+  EXPECT_EQ(stride_deco->stride, 64u);
   EXPECT_TRUE(p->error().empty());
 }
 
@@ -126,7 +126,7 @@
   EXPECT_TRUE(result[0]->Is<ast::StrideDecoration>());
   auto* stride_deco = result[0]->As<ast::StrideDecoration>();
   ASSERT_NE(stride_deco, nullptr);
-  EXPECT_EQ(stride_deco->stride(), 32u);
+  EXPECT_EQ(stride_deco->stride, 32u);
   EXPECT_TRUE(p->error().empty());
 }
 
diff --git a/src/reader/spirv/parser_type.cc b/src/reader/spirv/parser_type.cc
index 7556659..a8e03c6 100644
--- a/src/reader/spirv/parser_type.cc
+++ b/src/reader/spirv/parser_type.cc
@@ -565,15 +565,15 @@
 
 std::string Pointer::String() const {
   std::stringstream ss;
-  ss << "ptr<" << std::string(ast::str(storage_class)) << ", "
+  ss << "ptr<" << std::string(ast::ToString(storage_class)) << ", "
      << type->String() + ">";
   return ss.str();
 }
 
 std::string Reference::String() const {
   std::stringstream ss;
-  ss << "ref<" + std::string(ast::str(storage_class)) << ", " << type->String()
-     << ">";
+  ss << "ref<" + std::string(ast::ToString(storage_class)) << ", "
+     << type->String() << ">";
   return ss.str();
 }
 
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index c86277a..57c20ac 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -419,7 +419,7 @@
       if (!expect("struct declaration", Token::Type::kSemicolon))
         return Failure::kErrored;
 
-      register_type(builder_.Symbols().NameFor(str.value->name()), str.value);
+      register_type(builder_.Symbols().NameFor(str.value->name), str.value);
       builder_.AST().AddTypeDecl(str.value);
       return true;
     }
@@ -1791,7 +1791,7 @@
                             constructor,             // constructor
                             ast::DecorationList{});  // decorations
 
-  return create<ast::VariableDeclStatement>(var->source(), var);
+  return create<ast::VariableDeclStatement>(var->source, var);
 }
 
 // if_stmt
@@ -1946,7 +1946,7 @@
     } else if (!cond.matched) {
       break;
     } else if (!cond->Is<ast::IntLiteral>()) {
-      return add_error(cond.value->source(),
+      return add_error(cond.value->source,
                        "invalid case selector must be an integer value");
     }
 
@@ -3191,7 +3191,7 @@
   if (in.empty()) {
     return true;
   }
-  add_error(in[0]->source(), "unexpected decorations");
+  add_error(in[0]->source, "unexpected decorations");
   return false;
 }
 
diff --git a/src/reader/wgsl/parser_impl_additive_expression_test.cc b/src/reader/wgsl/parser_impl_additive_expression_test.cc
index 0a650fd..f6643d4 100644
--- a/src/reader/wgsl/parser_impl_additive_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_additive_expression_test.cc
@@ -29,17 +29,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kAdd, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kAdd, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
@@ -52,17 +52,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, AdditiveExpression_InvalidLHS) {
diff --git a/src/reader/wgsl/parser_impl_and_expression_test.cc b/src/reader/wgsl/parser_impl_and_expression_test.cc
index baebcda..64f715c 100644
--- a/src/reader/wgsl/parser_impl_and_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_and_expression_test.cc
@@ -29,17 +29,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kAnd, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kAnd, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Register("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, AndExpression_InvalidLHS) {
diff --git a/src/reader/wgsl/parser_impl_assignment_stmt_test.cc b/src/reader/wgsl/parser_impl_assignment_stmt_test.cc
index 07c59e9..ef4ec97 100644
--- a/src/reader/wgsl/parser_impl_assignment_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_assignment_stmt_test.cc
@@ -28,20 +28,20 @@
   ASSERT_NE(e.value, nullptr);
 
   ASSERT_TRUE(e->Is<ast::AssignmentStatement>());
-  ASSERT_NE(e->lhs(), nullptr);
-  ASSERT_NE(e->rhs(), nullptr);
+  ASSERT_NE(e->lhs, nullptr);
+  ASSERT_NE(e->rhs, nullptr);
 
-  ASSERT_TRUE(e->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = e->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(e->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = e->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(e->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(e->rhs()->Is<ast::ScalarConstructorExpression>());
+  ASSERT_TRUE(e->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(e->rhs->Is<ast::ScalarConstructorExpression>());
 
-  auto* init = e->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_NE(init->literal(), nullptr);
-  ASSERT_TRUE(init->literal()->Is<ast::SintLiteral>());
-  EXPECT_EQ(init->literal()->As<ast::SintLiteral>()->value(), 123);
+  auto* init = e->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_NE(init->literal, nullptr);
+  ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
+  EXPECT_EQ(init->literal->As<ast::SintLiteral>()->value, 123);
 }
 
 TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
@@ -53,49 +53,49 @@
   ASSERT_NE(e.value, nullptr);
 
   ASSERT_TRUE(e->Is<ast::AssignmentStatement>());
-  ASSERT_NE(e->lhs(), nullptr);
-  ASSERT_NE(e->rhs(), nullptr);
+  ASSERT_NE(e->lhs, nullptr);
+  ASSERT_NE(e->rhs, nullptr);
 
-  ASSERT_TRUE(e->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(e->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = e->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_NE(init->literal(), nullptr);
-  ASSERT_TRUE(init->literal()->Is<ast::SintLiteral>());
-  EXPECT_EQ(init->literal()->As<ast::SintLiteral>()->value(), 123);
+  ASSERT_TRUE(e->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(e->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = e->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_NE(init->literal, nullptr);
+  ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
+  EXPECT_EQ(init->literal->As<ast::SintLiteral>()->value, 123);
 
-  ASSERT_TRUE(e->lhs()->Is<ast::MemberAccessorExpression>());
-  auto* mem = e->lhs()->As<ast::MemberAccessorExpression>();
+  ASSERT_TRUE(e->lhs->Is<ast::MemberAccessorExpression>());
+  auto* mem = e->lhs->As<ast::MemberAccessorExpression>();
 
-  ASSERT_TRUE(mem->member()->Is<ast::IdentifierExpression>());
-  auto* ident = mem->member()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("d"));
+  ASSERT_TRUE(mem->member->Is<ast::IdentifierExpression>());
+  auto* ident = mem->member->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("d"));
 
-  ASSERT_TRUE(mem->structure()->Is<ast::ArrayAccessorExpression>());
-  auto* ary = mem->structure()->As<ast::ArrayAccessorExpression>();
+  ASSERT_TRUE(mem->structure->Is<ast::ArrayAccessorExpression>());
+  auto* ary = mem->structure->As<ast::ArrayAccessorExpression>();
 
-  ASSERT_TRUE(ary->idx_expr()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(ary->idx_expr()->Is<ast::ScalarConstructorExpression>());
-  init = ary->idx_expr()->As<ast::ScalarConstructorExpression>();
-  ASSERT_NE(init->literal(), nullptr);
-  ASSERT_TRUE(init->literal()->Is<ast::SintLiteral>());
-  EXPECT_EQ(init->literal()->As<ast::SintLiteral>()->value(), 2);
+  ASSERT_TRUE(ary->index->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(ary->index->Is<ast::ScalarConstructorExpression>());
+  init = ary->index->As<ast::ScalarConstructorExpression>();
+  ASSERT_NE(init->literal, nullptr);
+  ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
+  EXPECT_EQ(init->literal->As<ast::SintLiteral>()->value, 2);
 
-  ASSERT_TRUE(ary->array()->Is<ast::MemberAccessorExpression>());
-  mem = ary->array()->As<ast::MemberAccessorExpression>();
-  ASSERT_TRUE(mem->member()->Is<ast::IdentifierExpression>());
-  ident = mem->member()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("c"));
+  ASSERT_TRUE(ary->array->Is<ast::MemberAccessorExpression>());
+  mem = ary->array->As<ast::MemberAccessorExpression>();
+  ASSERT_TRUE(mem->member->Is<ast::IdentifierExpression>());
+  ident = mem->member->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("c"));
 
-  ASSERT_TRUE(mem->structure()->Is<ast::MemberAccessorExpression>());
-  mem = mem->structure()->As<ast::MemberAccessorExpression>();
+  ASSERT_TRUE(mem->structure->Is<ast::MemberAccessorExpression>());
+  mem = mem->structure->As<ast::MemberAccessorExpression>();
 
-  ASSERT_TRUE(mem->structure()->Is<ast::IdentifierExpression>());
-  ident = mem->structure()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(mem->structure->Is<ast::IdentifierExpression>());
+  ident = mem->structure->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(mem->member()->Is<ast::IdentifierExpression>());
-  ident = mem->member()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("b"));
+  ASSERT_TRUE(mem->member->Is<ast::IdentifierExpression>());
+  ident = mem->member->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, AssignmentStmt_MissingEqual) {
diff --git a/src/reader/wgsl/parser_impl_body_stmt_test.cc b/src/reader/wgsl/parser_impl_body_stmt_test.cc
index 73468e9..ee3df0a 100644
--- a/src/reader/wgsl/parser_impl_body_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_body_stmt_test.cc
@@ -28,9 +28,9 @@
   auto e = p->expect_body_stmt();
   ASSERT_FALSE(p->has_error()) << p->error();
   ASSERT_FALSE(e.errored);
-  ASSERT_EQ(e->size(), 2u);
-  EXPECT_TRUE(e->get(0)->Is<ast::DiscardStatement>());
-  EXPECT_TRUE(e->get(1)->Is<ast::ReturnStatement>());
+  ASSERT_EQ(e->statements.size(), 2u);
+  EXPECT_TRUE(e->statements[0]->Is<ast::DiscardStatement>());
+  EXPECT_TRUE(e->statements[1]->Is<ast::ReturnStatement>());
 }
 
 TEST_F(ParserImplTest, BodyStmt_Empty) {
@@ -38,7 +38,7 @@
   auto e = p->expect_body_stmt();
   ASSERT_FALSE(p->has_error()) << p->error();
   ASSERT_FALSE(e.errored);
-  EXPECT_EQ(e->size(), 0u);
+  EXPECT_EQ(e->statements.size(), 0u);
 }
 
 TEST_F(ParserImplTest, BodyStmt_InvalidStmt) {
diff --git a/src/reader/wgsl/parser_impl_call_stmt_test.cc b/src/reader/wgsl/parser_impl_call_stmt_test.cc
index 4e9b105..e38774f 100644
--- a/src/reader/wgsl/parser_impl_call_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_call_stmt_test.cc
@@ -28,17 +28,17 @@
   EXPECT_TRUE(e.matched);
   EXPECT_FALSE(e.errored);
 
-  EXPECT_EQ(e->source().range.begin.line, 1u);
-  EXPECT_EQ(e->source().range.begin.column, 1u);
-  EXPECT_EQ(e->source().range.end.line, 1u);
-  EXPECT_EQ(e->source().range.end.column, 2u);
+  EXPECT_EQ(e->source.range.begin.line, 1u);
+  EXPECT_EQ(e->source.range.begin.column, 1u);
+  EXPECT_EQ(e->source.range.end.line, 1u);
+  EXPECT_EQ(e->source.range.end.column, 2u);
 
   ASSERT_TRUE(e->Is<ast::CallStatement>());
-  auto* c = e->As<ast::CallStatement>()->expr();
+  auto* c = e->As<ast::CallStatement>()->expr;
 
-  EXPECT_EQ(c->func()->symbol(), p->builder().Symbols().Get("a"));
+  EXPECT_EQ(c->func->symbol, p->builder().Symbols().Get("a"));
 
-  EXPECT_EQ(c->args().size(), 0u);
+  EXPECT_EQ(c->args.size(), 0u);
 }
 
 TEST_F(ParserImplTest, Statement_Call_WithParams) {
@@ -50,14 +50,14 @@
   EXPECT_FALSE(e.errored);
 
   ASSERT_TRUE(e->Is<ast::CallStatement>());
-  auto* c = e->As<ast::CallStatement>()->expr();
+  auto* c = e->As<ast::CallStatement>()->expr;
 
-  EXPECT_EQ(c->func()->symbol(), p->builder().Symbols().Get("a"));
+  EXPECT_EQ(c->func->symbol, p->builder().Symbols().Get("a"));
 
-  EXPECT_EQ(c->args().size(), 3u);
-  EXPECT_TRUE(c->args()[0]->Is<ast::ConstructorExpression>());
-  EXPECT_TRUE(c->args()[1]->Is<ast::IdentifierExpression>());
-  EXPECT_TRUE(c->args()[2]->Is<ast::BinaryExpression>());
+  EXPECT_EQ(c->args.size(), 3u);
+  EXPECT_TRUE(c->args[0]->Is<ast::ConstructorExpression>());
+  EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>());
+  EXPECT_TRUE(c->args[2]->Is<ast::BinaryExpression>());
 }
 
 TEST_F(ParserImplTest, Statement_Call_WithParams_TrailingComma) {
@@ -69,13 +69,13 @@
   EXPECT_FALSE(e.errored);
 
   ASSERT_TRUE(e->Is<ast::CallStatement>());
-  auto* c = e->As<ast::CallStatement>()->expr();
+  auto* c = e->As<ast::CallStatement>()->expr;
 
-  EXPECT_EQ(c->func()->symbol(), p->builder().Symbols().Get("a"));
+  EXPECT_EQ(c->func->symbol, p->builder().Symbols().Get("a"));
 
-  EXPECT_EQ(c->args().size(), 2u);
-  EXPECT_TRUE(c->args()[0]->Is<ast::ConstructorExpression>());
-  EXPECT_TRUE(c->args()[1]->Is<ast::IdentifierExpression>());
+  EXPECT_EQ(c->args.size(), 2u);
+  EXPECT_TRUE(c->args[0]->Is<ast::ConstructorExpression>());
+  EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>());
 }
 
 TEST_F(ParserImplTest, Statement_Call_Missing_RightParen) {
diff --git a/src/reader/wgsl/parser_impl_case_body_test.cc b/src/reader/wgsl/parser_impl_case_body_test.cc
index 6edf7c5..0237cdb 100644
--- a/src/reader/wgsl/parser_impl_case_body_test.cc
+++ b/src/reader/wgsl/parser_impl_case_body_test.cc
@@ -26,7 +26,7 @@
   ASSERT_FALSE(p->has_error()) << p->error();
   EXPECT_FALSE(e.errored);
   EXPECT_TRUE(e.matched);
-  EXPECT_EQ(e->size(), 0u);
+  EXPECT_EQ(e->statements.size(), 0u);
 }
 
 TEST_F(ParserImplTest, CaseBody_Statements) {
@@ -38,9 +38,9 @@
   ASSERT_FALSE(p->has_error()) << p->error();
   EXPECT_FALSE(e.errored);
   EXPECT_TRUE(e.matched);
-  ASSERT_EQ(e->size(), 2u);
-  EXPECT_TRUE(e->get(0)->Is<ast::VariableDeclStatement>());
-  EXPECT_TRUE(e->get(1)->Is<ast::AssignmentStatement>());
+  ASSERT_EQ(e->statements.size(), 2u);
+  EXPECT_TRUE(e->statements[0]->Is<ast::VariableDeclStatement>());
+  EXPECT_TRUE(e->statements[1]->Is<ast::AssignmentStatement>());
 }
 
 TEST_F(ParserImplTest, CaseBody_InvalidStatement) {
@@ -58,8 +58,8 @@
   ASSERT_FALSE(p->has_error()) << p->error();
   EXPECT_FALSE(e.errored);
   EXPECT_TRUE(e.matched);
-  ASSERT_EQ(e->size(), 1u);
-  EXPECT_TRUE(e->get(0)->Is<ast::FallthroughStatement>());
+  ASSERT_EQ(e->statements.size(), 1u);
+  EXPECT_TRUE(e->statements[0]->Is<ast::FallthroughStatement>());
 }
 
 TEST_F(ParserImplTest, CaseBody_Fallthrough_MissingSemicolon) {
diff --git a/src/reader/wgsl/parser_impl_const_expr_test.cc b/src/reader/wgsl/parser_impl_const_expr_test.cc
index 3f313ab..a37f6e0 100644
--- a/src/reader/wgsl/parser_impl_const_expr_test.cc
+++ b/src/reader/wgsl/parser_impl_const_expr_test.cc
@@ -28,23 +28,23 @@
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
 
   auto* t = e->As<ast::TypeConstructorExpression>();
-  ASSERT_TRUE(t->type()->Is<ast::Vector>());
-  EXPECT_EQ(t->type()->As<ast::Vector>()->size(), 2u);
+  ASSERT_TRUE(t->type->Is<ast::Vector>());
+  EXPECT_EQ(t->type->As<ast::Vector>()->width, 2u);
 
-  ASSERT_EQ(t->values().size(), 2u);
-  auto& v = t->values();
+  ASSERT_EQ(t->values.size(), 2u);
+  auto& v = t->values;
 
   ASSERT_TRUE(v[0]->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(v[0]->Is<ast::ScalarConstructorExpression>());
   auto* c = v[0]->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(c->literal()->Is<ast::FloatLiteral>());
-  EXPECT_FLOAT_EQ(c->literal()->As<ast::FloatLiteral>()->value(), 1.);
+  ASSERT_TRUE(c->literal->Is<ast::FloatLiteral>());
+  EXPECT_FLOAT_EQ(c->literal->As<ast::FloatLiteral>()->value, 1.);
 
   ASSERT_TRUE(v[1]->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(v[1]->Is<ast::ScalarConstructorExpression>());
   c = v[1]->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(c->literal()->Is<ast::FloatLiteral>());
-  EXPECT_FLOAT_EQ(c->literal()->As<ast::FloatLiteral>()->value(), 2.);
+  ASSERT_TRUE(c->literal->Is<ast::FloatLiteral>());
+  EXPECT_FLOAT_EQ(c->literal->As<ast::FloatLiteral>()->value, 2.);
 }
 
 TEST_F(ParserImplTest, ConstExpr_TypeDecl_Empty) {
@@ -56,10 +56,10 @@
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
 
   auto* t = e->As<ast::TypeConstructorExpression>();
-  ASSERT_TRUE(t->type()->Is<ast::Vector>());
-  EXPECT_EQ(t->type()->As<ast::Vector>()->size(), 2u);
+  ASSERT_TRUE(t->type->Is<ast::Vector>());
+  EXPECT_EQ(t->type->As<ast::Vector>()->width, 2u);
 
-  ASSERT_EQ(t->values().size(), 0u);
+  ASSERT_EQ(t->values.size(), 0u);
 }
 
 TEST_F(ParserImplTest, ConstExpr_TypeDecl_TrailingComma) {
@@ -71,12 +71,12 @@
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
 
   auto* t = e->As<ast::TypeConstructorExpression>();
-  ASSERT_TRUE(t->type()->Is<ast::Vector>());
-  EXPECT_EQ(t->type()->As<ast::Vector>()->size(), 2u);
+  ASSERT_TRUE(t->type->Is<ast::Vector>());
+  EXPECT_EQ(t->type->As<ast::Vector>()->width, 2u);
 
-  ASSERT_EQ(t->values().size(), 2u);
-  ASSERT_TRUE(t->values()[0]->Is<ast::ScalarConstructorExpression>());
-  ASSERT_TRUE(t->values()[1]->Is<ast::ScalarConstructorExpression>());
+  ASSERT_EQ(t->values.size(), 2u);
+  ASSERT_TRUE(t->values[0]->Is<ast::ScalarConstructorExpression>());
+  ASSERT_TRUE(t->values[1]->Is<ast::ScalarConstructorExpression>());
 }
 
 TEST_F(ParserImplTest, ConstExpr_TypeDecl_MissingRightParen) {
@@ -124,8 +124,8 @@
   ASSERT_TRUE(e->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(e->Is<ast::ScalarConstructorExpression>());
   auto* c = e->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(c->literal()->Is<ast::BoolLiteral>());
-  EXPECT_TRUE(c->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(c->literal->Is<ast::BoolLiteral>());
+  EXPECT_TRUE(c->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, ConstExpr_ConstLiteral_Invalid) {
diff --git a/src/reader/wgsl/parser_impl_const_literal_test.cc b/src/reader/wgsl/parser_impl_const_literal_test.cc
index 16e3472..33d972c 100644
--- a/src/reader/wgsl/parser_impl_const_literal_test.cc
+++ b/src/reader/wgsl/parser_impl_const_literal_test.cc
@@ -49,8 +49,8 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(c.value, nullptr);
   ASSERT_TRUE(c->Is<ast::SintLiteral>());
-  EXPECT_EQ(c->As<ast::SintLiteral>()->value(), -234);
-  EXPECT_EQ(c->source().range, (Source::Range{{1u, 1u}, {1u, 5u}}));
+  EXPECT_EQ(c->As<ast::SintLiteral>()->value, -234);
+  EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 5u}}));
 }
 
 TEST_F(ParserImplTest, ConstLiteral_Uint) {
@@ -61,8 +61,8 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(c.value, nullptr);
   ASSERT_TRUE(c->Is<ast::UintLiteral>());
-  EXPECT_EQ(c->As<ast::UintLiteral>()->value(), 234u);
-  EXPECT_EQ(c->source().range, (Source::Range{{1u, 1u}, {1u, 5u}}));
+  EXPECT_EQ(c->As<ast::UintLiteral>()->value, 234u);
+  EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 5u}}));
 }
 
 TEST_F(ParserImplTest, ConstLiteral_Float) {
@@ -73,8 +73,8 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(c.value, nullptr);
   ASSERT_TRUE(c->Is<ast::FloatLiteral>());
-  EXPECT_FLOAT_EQ(c->As<ast::FloatLiteral>()->value(), 234e12f);
-  EXPECT_EQ(c->source().range, (Source::Range{{1u, 1u}, {1u, 8u}}));
+  EXPECT_FLOAT_EQ(c->As<ast::FloatLiteral>()->value, 234e12f);
+  EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 8u}}));
 }
 
 TEST_F(ParserImplTest, ConstLiteral_InvalidFloat) {
@@ -108,7 +108,7 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(c.value, nullptr);
   ASSERT_TRUE(c->Is<ast::FloatLiteral>());
-  EXPECT_FLOAT_EQ(c->As<ast::FloatLiteral>()->value(), params.expected);
+  EXPECT_FLOAT_EQ(c->As<ast::FloatLiteral>()->value, params.expected);
 }
 
 FloatLiteralTestCase float_literal_test_cases[] = {
@@ -366,9 +366,9 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(c.value, nullptr);
   ASSERT_TRUE(c->Is<ast::FloatLiteral>());
-  EXPECT_FLOAT_EQ(c->As<ast::FloatLiteral>()->value(),
+  EXPECT_FLOAT_EQ(c->As<ast::FloatLiteral>()->value,
                   std::numeric_limits<float>::max());
-  EXPECT_EQ(c->source().range, (Source::Range{{1u, 1u}, {1u, 42u}}));
+  EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 42u}}));
 }
 
 TEST_F(ParserImplTest, ConstLiteral_FloatLowest) {
@@ -389,9 +389,9 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(c.value, nullptr);
   ASSERT_TRUE(c->Is<ast::FloatLiteral>());
-  EXPECT_FLOAT_EQ(c->As<ast::FloatLiteral>()->value(),
+  EXPECT_FLOAT_EQ(c->As<ast::FloatLiteral>()->value,
                   std::numeric_limits<float>::lowest());
-  EXPECT_EQ(c->source().range, (Source::Range{{1u, 1u}, {1u, 43u}}));
+  EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 43u}}));
 }
 
 TEST_F(ParserImplTest, ConstLiteral_True) {
@@ -402,8 +402,8 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(c.value, nullptr);
   ASSERT_TRUE(c->Is<ast::BoolLiteral>());
-  EXPECT_TRUE(c->As<ast::BoolLiteral>()->IsTrue());
-  EXPECT_EQ(c->source().range, (Source::Range{{1u, 1u}, {1u, 5u}}));
+  EXPECT_TRUE(c->As<ast::BoolLiteral>()->value);
+  EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 5u}}));
 }
 
 TEST_F(ParserImplTest, ConstLiteral_False) {
@@ -414,8 +414,8 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(c.value, nullptr);
   ASSERT_TRUE(c->Is<ast::BoolLiteral>());
-  EXPECT_TRUE(c->As<ast::BoolLiteral>()->IsFalse());
-  EXPECT_EQ(c->source().range, (Source::Range{{1u, 1u}, {1u, 6u}}));
+  EXPECT_FALSE(c->As<ast::BoolLiteral>()->value);
+  EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 6u}}));
 }
 
 TEST_F(ParserImplTest, ConstLiteral_NoMatch) {
diff --git a/src/reader/wgsl/parser_impl_continuing_stmt_test.cc b/src/reader/wgsl/parser_impl_continuing_stmt_test.cc
index 22706e9..27714ff 100644
--- a/src/reader/wgsl/parser_impl_continuing_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_continuing_stmt_test.cc
@@ -26,8 +26,8 @@
   EXPECT_TRUE(e.matched);
   EXPECT_FALSE(e.errored);
   EXPECT_FALSE(p->has_error()) << p->error();
-  ASSERT_EQ(e->size(), 1u);
-  ASSERT_TRUE(e->get(0)->Is<ast::DiscardStatement>());
+  ASSERT_EQ(e->statements.size(), 1u);
+  ASSERT_TRUE(e->statements[0]->Is<ast::DiscardStatement>());
 }
 
 TEST_F(ParserImplTest, ContinuingStmt_InvalidBody) {
diff --git a/src/reader/wgsl/parser_impl_depth_texture_type_test.cc b/src/reader/wgsl/parser_impl_depth_texture_type_test.cc
index 0102296..da5e080 100644
--- a/src/reader/wgsl/parser_impl_depth_texture_type_test.cc
+++ b/src/reader/wgsl/parser_impl_depth_texture_type_test.cc
@@ -36,9 +36,9 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::Texture>());
   ASSERT_TRUE(t->Is<ast::DepthTexture>());
-  EXPECT_EQ(t->As<ast::Texture>()->dim(), ast::TextureDimension::k2d);
+  EXPECT_EQ(t->As<ast::Texture>()->dim, ast::TextureDimension::k2d);
   EXPECT_FALSE(p->has_error());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 17u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 17u}}));
 }
 
 TEST_F(ParserImplTest, DepthTextureType_2dArray) {
@@ -49,9 +49,9 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::Texture>());
   ASSERT_TRUE(t->Is<ast::DepthTexture>());
-  EXPECT_EQ(t->As<ast::Texture>()->dim(), ast::TextureDimension::k2dArray);
+  EXPECT_EQ(t->As<ast::Texture>()->dim, ast::TextureDimension::k2dArray);
   EXPECT_FALSE(p->has_error());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 23u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 23u}}));
 }
 
 TEST_F(ParserImplTest, DepthTextureType_Cube) {
@@ -62,9 +62,9 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::Texture>());
   ASSERT_TRUE(t->Is<ast::DepthTexture>());
-  EXPECT_EQ(t->As<ast::Texture>()->dim(), ast::TextureDimension::kCube);
+  EXPECT_EQ(t->As<ast::Texture>()->dim, ast::TextureDimension::kCube);
   EXPECT_FALSE(p->has_error());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 19u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 19u}}));
 }
 
 TEST_F(ParserImplTest, DepthTextureType_CubeArray) {
@@ -75,9 +75,9 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::Texture>());
   ASSERT_TRUE(t->Is<ast::DepthTexture>());
-  EXPECT_EQ(t->As<ast::Texture>()->dim(), ast::TextureDimension::kCubeArray);
+  EXPECT_EQ(t->As<ast::Texture>()->dim, ast::TextureDimension::kCubeArray);
   EXPECT_FALSE(p->has_error());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 25u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 25u}}));
 }
 
 TEST_F(ParserImplTest, DepthTextureType_Multisampled2d) {
@@ -88,9 +88,9 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::Texture>());
   ASSERT_TRUE(t->Is<ast::DepthMultisampledTexture>());
-  EXPECT_EQ(t->As<ast::Texture>()->dim(), ast::TextureDimension::k2d);
+  EXPECT_EQ(t->As<ast::Texture>()->dim, ast::TextureDimension::k2d);
   EXPECT_FALSE(p->has_error());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 30u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 30u}}));
 }
 
 }  // namespace
diff --git a/src/reader/wgsl/parser_impl_else_stmt_test.cc b/src/reader/wgsl/parser_impl_else_stmt_test.cc
index 4d2f87b..822602b 100644
--- a/src/reader/wgsl/parser_impl_else_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_else_stmt_test.cc
@@ -27,8 +27,8 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::ElseStatement>());
-  ASSERT_EQ(e->condition(), nullptr);
-  EXPECT_EQ(e->body()->size(), 2u);
+  ASSERT_EQ(e->condition, nullptr);
+  EXPECT_EQ(e->body->statements.size(), 2u);
 }
 
 TEST_F(ParserImplTest, ElseStmt_InvalidBody) {
diff --git a/src/reader/wgsl/parser_impl_elseif_stmt_test.cc b/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
index 7051f47..ade3c99 100644
--- a/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_elseif_stmt_test.cc
@@ -28,9 +28,9 @@
   ASSERT_EQ(e.value.size(), 1u);
 
   ASSERT_TRUE(e.value[0]->Is<ast::ElseStatement>());
-  ASSERT_NE(e.value[0]->condition(), nullptr);
-  ASSERT_TRUE(e.value[0]->condition()->Is<ast::BinaryExpression>());
-  EXPECT_EQ(e.value[0]->body()->size(), 2u);
+  ASSERT_NE(e.value[0]->condition, nullptr);
+  ASSERT_TRUE(e.value[0]->condition->Is<ast::BinaryExpression>());
+  EXPECT_EQ(e.value[0]->body->statements.size(), 2u);
 }
 
 TEST_F(ParserImplTest, ElseIfStmt_Multiple) {
@@ -42,14 +42,14 @@
   ASSERT_EQ(e.value.size(), 2u);
 
   ASSERT_TRUE(e.value[0]->Is<ast::ElseStatement>());
-  ASSERT_NE(e.value[0]->condition(), nullptr);
-  ASSERT_TRUE(e.value[0]->condition()->Is<ast::BinaryExpression>());
-  EXPECT_EQ(e.value[0]->body()->size(), 2u);
+  ASSERT_NE(e.value[0]->condition, nullptr);
+  ASSERT_TRUE(e.value[0]->condition->Is<ast::BinaryExpression>());
+  EXPECT_EQ(e.value[0]->body->statements.size(), 2u);
 
   ASSERT_TRUE(e.value[1]->Is<ast::ElseStatement>());
-  ASSERT_NE(e.value[1]->condition(), nullptr);
-  ASSERT_TRUE(e.value[1]->condition()->Is<ast::IdentifierExpression>());
-  EXPECT_EQ(e.value[1]->body()->size(), 1u);
+  ASSERT_NE(e.value[1]->condition, nullptr);
+  ASSERT_TRUE(e.value[1]->condition->Is<ast::IdentifierExpression>());
+  EXPECT_EQ(e.value[1]->body->statements.size(), 1u);
 }
 
 TEST_F(ParserImplTest, ElseIfStmt_InvalidBody) {
diff --git a/src/reader/wgsl/parser_impl_equality_expression_test.cc b/src/reader/wgsl/parser_impl_equality_expression_test.cc
index d23f6b6..8350e96 100644
--- a/src/reader/wgsl/parser_impl_equality_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_equality_expression_test.cc
@@ -29,17 +29,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kEqual, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kEqual, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, EqualityExpression_Parses_NotEqual) {
@@ -52,17 +52,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kNotEqual, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kNotEqual, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, EqualityExpression_InvalidLHS) {
diff --git a/src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc b/src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc
index 08608c8..bfcbf94 100644
--- a/src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_exclusive_or_expression_test.cc
@@ -29,17 +29,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kXor, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kXor, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, ExclusiveOrExpression_InvalidLHS) {
diff --git a/src/reader/wgsl/parser_impl_external_texture_type_test.cc b/src/reader/wgsl/parser_impl_external_texture_type_test.cc
index 35f4c40..f09e083 100644
--- a/src/reader/wgsl/parser_impl_external_texture_type_test.cc
+++ b/src/reader/wgsl/parser_impl_external_texture_type_test.cc
@@ -32,7 +32,7 @@
   auto t = p->external_texture_type();
   EXPECT_TRUE(t.matched);
   EXPECT_FALSE(t.errored);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 17u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 17u}}));
 }
 
 }  // namespace
diff --git a/src/reader/wgsl/parser_impl_for_stmt_test.cc b/src/reader/wgsl/parser_impl_for_stmt_test.cc
index 1aac60e..ba36f9d 100644
--- a/src/reader/wgsl/parser_impl_for_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_for_stmt_test.cc
@@ -30,10 +30,10 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   EXPECT_FALSE(fl.errored);
   ASSERT_TRUE(fl.matched);
-  EXPECT_EQ(fl->initializer(), nullptr);
-  EXPECT_EQ(fl->condition(), nullptr);
-  EXPECT_EQ(fl->continuing(), nullptr);
-  EXPECT_TRUE(fl->body()->empty());
+  EXPECT_EQ(fl->initializer, nullptr);
+  EXPECT_EQ(fl->condition, nullptr);
+  EXPECT_EQ(fl->continuing, nullptr);
+  EXPECT_TRUE(fl->body->Empty());
 }
 
 // Test a for loop with non-empty body.
@@ -43,11 +43,11 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   EXPECT_FALSE(fl.errored);
   ASSERT_TRUE(fl.matched);
-  EXPECT_EQ(fl->initializer(), nullptr);
-  EXPECT_EQ(fl->condition(), nullptr);
-  EXPECT_EQ(fl->continuing(), nullptr);
-  ASSERT_EQ(fl->body()->size(), 1u);
-  EXPECT_TRUE(fl->body()->statements()[0]->Is<ast::DiscardStatement>());
+  EXPECT_EQ(fl->initializer, nullptr);
+  EXPECT_EQ(fl->condition, nullptr);
+  EXPECT_EQ(fl->continuing, nullptr);
+  ASSERT_EQ(fl->body->statements.size(), 1u);
+  EXPECT_TRUE(fl->body->statements[0]->Is<ast::DiscardStatement>());
 }
 
 // Test a for loop declaring a variable in the initializer statement.
@@ -57,13 +57,13 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   EXPECT_FALSE(fl.errored);
   ASSERT_TRUE(fl.matched);
-  ASSERT_TRUE(Is<ast::VariableDeclStatement>(fl->initializer()));
-  auto* var = fl->initializer()->As<ast::VariableDeclStatement>()->variable();
-  EXPECT_FALSE(var->is_const());
-  EXPECT_EQ(var->constructor(), nullptr);
-  EXPECT_EQ(fl->condition(), nullptr);
-  EXPECT_EQ(fl->continuing(), nullptr);
-  EXPECT_TRUE(fl->body()->empty());
+  ASSERT_TRUE(Is<ast::VariableDeclStatement>(fl->initializer));
+  auto* var = fl->initializer->As<ast::VariableDeclStatement>()->variable;
+  EXPECT_FALSE(var->is_const);
+  EXPECT_EQ(var->constructor, nullptr);
+  EXPECT_EQ(fl->condition, nullptr);
+  EXPECT_EQ(fl->continuing, nullptr);
+  EXPECT_TRUE(fl->body->Empty());
 }
 
 // Test a for loop declaring and initializing a variable in the initializer
@@ -74,13 +74,13 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   EXPECT_FALSE(fl.errored);
   ASSERT_TRUE(fl.matched);
-  ASSERT_TRUE(Is<ast::VariableDeclStatement>(fl->initializer()));
-  auto* var = fl->initializer()->As<ast::VariableDeclStatement>()->variable();
-  EXPECT_FALSE(var->is_const());
-  EXPECT_NE(var->constructor(), nullptr);
-  EXPECT_EQ(fl->condition(), nullptr);
-  EXPECT_EQ(fl->continuing(), nullptr);
-  EXPECT_TRUE(fl->body()->empty());
+  ASSERT_TRUE(Is<ast::VariableDeclStatement>(fl->initializer));
+  auto* var = fl->initializer->As<ast::VariableDeclStatement>()->variable;
+  EXPECT_FALSE(var->is_const);
+  EXPECT_NE(var->constructor, nullptr);
+  EXPECT_EQ(fl->condition, nullptr);
+  EXPECT_EQ(fl->continuing, nullptr);
+  EXPECT_TRUE(fl->body->Empty());
 }
 
 // Test a for loop declaring a const variable in the initializer statement.
@@ -90,13 +90,13 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   EXPECT_FALSE(fl.errored);
   ASSERT_TRUE(fl.matched);
-  ASSERT_TRUE(Is<ast::VariableDeclStatement>(fl->initializer()));
-  auto* var = fl->initializer()->As<ast::VariableDeclStatement>()->variable();
-  EXPECT_TRUE(var->is_const());
-  EXPECT_NE(var->constructor(), nullptr);
-  EXPECT_EQ(fl->condition(), nullptr);
-  EXPECT_EQ(fl->continuing(), nullptr);
-  EXPECT_TRUE(fl->body()->empty());
+  ASSERT_TRUE(Is<ast::VariableDeclStatement>(fl->initializer));
+  auto* var = fl->initializer->As<ast::VariableDeclStatement>()->variable;
+  EXPECT_TRUE(var->is_const);
+  EXPECT_NE(var->constructor, nullptr);
+  EXPECT_EQ(fl->condition, nullptr);
+  EXPECT_EQ(fl->continuing, nullptr);
+  EXPECT_TRUE(fl->body->Empty());
 }
 
 // Test a for loop assigning a variable in the initializer statement.
@@ -106,10 +106,10 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   EXPECT_FALSE(fl.errored);
   ASSERT_TRUE(fl.matched);
-  EXPECT_TRUE(Is<ast::AssignmentStatement>(fl->initializer()));
-  EXPECT_EQ(fl->condition(), nullptr);
-  EXPECT_EQ(fl->continuing(), nullptr);
-  EXPECT_TRUE(fl->body()->empty());
+  EXPECT_TRUE(Is<ast::AssignmentStatement>(fl->initializer));
+  EXPECT_EQ(fl->condition, nullptr);
+  EXPECT_EQ(fl->continuing, nullptr);
+  EXPECT_TRUE(fl->body->Empty());
 }
 
 // Test a for loop calling a function in the initializer statement.
@@ -119,10 +119,10 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   EXPECT_FALSE(fl.errored);
   ASSERT_TRUE(fl.matched);
-  EXPECT_TRUE(Is<ast::CallStatement>(fl->initializer()));
-  EXPECT_EQ(fl->condition(), nullptr);
-  EXPECT_EQ(fl->continuing(), nullptr);
-  EXPECT_TRUE(fl->body()->empty());
+  EXPECT_TRUE(Is<ast::CallStatement>(fl->initializer));
+  EXPECT_EQ(fl->condition, nullptr);
+  EXPECT_EQ(fl->continuing, nullptr);
+  EXPECT_TRUE(fl->body->Empty());
 }
 
 // Test a for loop with a break condition
@@ -132,10 +132,10 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   EXPECT_FALSE(fl.errored);
   ASSERT_TRUE(fl.matched);
-  EXPECT_EQ(fl->initializer(), nullptr);
-  EXPECT_TRUE(Is<ast::BinaryExpression>(fl->condition()));
-  EXPECT_EQ(fl->continuing(), nullptr);
-  EXPECT_TRUE(fl->body()->empty());
+  EXPECT_EQ(fl->initializer, nullptr);
+  EXPECT_TRUE(Is<ast::BinaryExpression>(fl->condition));
+  EXPECT_EQ(fl->continuing, nullptr);
+  EXPECT_TRUE(fl->body->Empty());
 }
 
 // Test a for loop assigning a variable in the continuing statement.
@@ -145,10 +145,10 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   EXPECT_FALSE(fl.errored);
   ASSERT_TRUE(fl.matched);
-  EXPECT_EQ(fl->initializer(), nullptr);
-  EXPECT_EQ(fl->condition(), nullptr);
-  EXPECT_TRUE(Is<ast::AssignmentStatement>(fl->continuing()));
-  EXPECT_TRUE(fl->body()->empty());
+  EXPECT_EQ(fl->initializer, nullptr);
+  EXPECT_EQ(fl->condition, nullptr);
+  EXPECT_TRUE(Is<ast::AssignmentStatement>(fl->continuing));
+  EXPECT_TRUE(fl->body->Empty());
 }
 
 // Test a for loop calling a function in the continuing statement.
@@ -158,10 +158,10 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   EXPECT_FALSE(fl.errored);
   ASSERT_TRUE(fl.matched);
-  EXPECT_EQ(fl->initializer(), nullptr);
-  EXPECT_EQ(fl->condition(), nullptr);
-  EXPECT_TRUE(Is<ast::CallStatement>(fl->continuing()));
-  EXPECT_TRUE(fl->body()->empty());
+  EXPECT_EQ(fl->initializer, nullptr);
+  EXPECT_EQ(fl->condition, nullptr);
+  EXPECT_TRUE(Is<ast::CallStatement>(fl->continuing));
+  EXPECT_TRUE(fl->body->Empty());
 }
 
 class ForStmtErrorTest : public ParserImplTest {
diff --git a/src/reader/wgsl/parser_impl_function_decl_test.cc b/src/reader/wgsl/parser_impl_function_decl_test.cc
index f08db28..2ec9a8d 100644
--- a/src/reader/wgsl/parser_impl_function_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_function_decl_test.cc
@@ -32,20 +32,20 @@
   EXPECT_TRUE(f.matched);
   ASSERT_NE(f.value, nullptr);
 
-  EXPECT_EQ(f->symbol(), p->builder().Symbols().Get("main"));
-  ASSERT_NE(f->return_type(), nullptr);
-  EXPECT_TRUE(f->return_type()->Is<ast::Void>());
+  EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
+  ASSERT_NE(f->return_type, nullptr);
+  EXPECT_TRUE(f->return_type->Is<ast::Void>());
 
-  ASSERT_EQ(f->params().size(), 2u);
-  EXPECT_EQ(f->params()[0]->symbol(), p->builder().Symbols().Get("a"));
-  EXPECT_EQ(f->params()[1]->symbol(), p->builder().Symbols().Get("b"));
+  ASSERT_EQ(f->params.size(), 2u);
+  EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get("a"));
+  EXPECT_EQ(f->params[1]->symbol, p->builder().Symbols().Get("b"));
 
-  ASSERT_NE(f->return_type(), nullptr);
-  EXPECT_TRUE(f->return_type()->Is<ast::Void>());
+  ASSERT_NE(f->return_type, nullptr);
+  EXPECT_TRUE(f->return_type->Is<ast::Void>());
 
-  auto* body = f->body();
-  ASSERT_EQ(body->size(), 1u);
-  EXPECT_TRUE(body->get(0)->Is<ast::ReturnStatement>());
+  auto* body = f->body;
+  ASSERT_EQ(body->statements.size(), 1u);
+  EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
 }
 
 TEST_F(ParserImplTest, FunctionDecl_DecorationList) {
@@ -60,38 +60,38 @@
   EXPECT_TRUE(f.matched);
   ASSERT_NE(f.value, nullptr);
 
-  EXPECT_EQ(f->symbol(), p->builder().Symbols().Get("main"));
-  ASSERT_NE(f->return_type(), nullptr);
-  EXPECT_TRUE(f->return_type()->Is<ast::Void>());
-  ASSERT_EQ(f->params().size(), 0u);
+  EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
+  ASSERT_NE(f->return_type, nullptr);
+  EXPECT_TRUE(f->return_type->Is<ast::Void>());
+  ASSERT_EQ(f->params.size(), 0u);
 
-  auto& decorations = f->decorations();
+  auto& decorations = f->decorations;
   ASSERT_EQ(decorations.size(), 1u);
   ASSERT_TRUE(decorations[0]->Is<ast::WorkgroupDecoration>());
 
-  auto values = decorations[0]->As<ast::WorkgroupDecoration>()->values();
+  auto values = decorations[0]->As<ast::WorkgroupDecoration>()->Values();
 
   ASSERT_NE(values[0], nullptr);
   auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(x_scalar, nullptr);
-  ASSERT_TRUE(x_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(x_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 2u);
+  ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
 
   ASSERT_NE(values[1], nullptr);
   auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(y_scalar, nullptr);
-  ASSERT_TRUE(y_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(y_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 3u);
+  ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 3u);
 
   ASSERT_NE(values[2], nullptr);
   auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(z_scalar, nullptr);
-  ASSERT_TRUE(z_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(z_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 4u);
+  ASSERT_TRUE(z_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(z_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
 
-  auto* body = f->body();
-  ASSERT_EQ(body->size(), 1u);
-  EXPECT_TRUE(body->get(0)->Is<ast::ReturnStatement>());
+  auto* body = f->body;
+  ASSERT_EQ(body->statements.size(), 1u);
+  EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
 }
 
 TEST_F(ParserImplTest, FunctionDecl_DecorationList_MultipleEntries) {
@@ -108,42 +108,42 @@
   EXPECT_TRUE(f.matched);
   ASSERT_NE(f.value, nullptr);
 
-  EXPECT_EQ(f->symbol(), p->builder().Symbols().Get("main"));
-  ASSERT_NE(f->return_type(), nullptr);
-  EXPECT_TRUE(f->return_type()->Is<ast::Void>());
-  ASSERT_EQ(f->params().size(), 0u);
+  EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
+  ASSERT_NE(f->return_type, nullptr);
+  EXPECT_TRUE(f->return_type->Is<ast::Void>());
+  ASSERT_EQ(f->params.size(), 0u);
 
-  auto& decorations = f->decorations();
+  auto& decorations = f->decorations;
   ASSERT_EQ(decorations.size(), 2u);
 
   ASSERT_TRUE(decorations[0]->Is<ast::WorkgroupDecoration>());
-  auto values = decorations[0]->As<ast::WorkgroupDecoration>()->values();
+  auto values = decorations[0]->As<ast::WorkgroupDecoration>()->Values();
 
   ASSERT_NE(values[0], nullptr);
   auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(x_scalar, nullptr);
-  ASSERT_TRUE(x_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(x_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 2u);
+  ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
 
   ASSERT_NE(values[1], nullptr);
   auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(y_scalar, nullptr);
-  ASSERT_TRUE(y_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(y_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 3u);
+  ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 3u);
 
   ASSERT_NE(values[2], nullptr);
   auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(z_scalar, nullptr);
-  ASSERT_TRUE(z_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(z_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 4u);
+  ASSERT_TRUE(z_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(z_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
 
   ASSERT_TRUE(decorations[1]->Is<ast::StageDecoration>());
-  EXPECT_EQ(decorations[1]->As<ast::StageDecoration>()->value(),
+  EXPECT_EQ(decorations[1]->As<ast::StageDecoration>()->stage,
             ast::PipelineStage::kCompute);
 
-  auto* body = f->body();
-  ASSERT_EQ(body->size(), 1u);
-  EXPECT_TRUE(body->get(0)->Is<ast::ReturnStatement>());
+  auto* body = f->body;
+  ASSERT_EQ(body->statements.size(), 1u);
+  EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
 }
 
 TEST_F(ParserImplTest, FunctionDecl_DecorationList_MultipleLists) {
@@ -161,42 +161,42 @@
   EXPECT_TRUE(f.matched);
   ASSERT_NE(f.value, nullptr);
 
-  EXPECT_EQ(f->symbol(), p->builder().Symbols().Get("main"));
-  ASSERT_NE(f->return_type(), nullptr);
-  EXPECT_TRUE(f->return_type()->Is<ast::Void>());
-  ASSERT_EQ(f->params().size(), 0u);
+  EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
+  ASSERT_NE(f->return_type, nullptr);
+  EXPECT_TRUE(f->return_type->Is<ast::Void>());
+  ASSERT_EQ(f->params.size(), 0u);
 
-  auto& decos = f->decorations();
+  auto& decos = f->decorations;
   ASSERT_EQ(decos.size(), 2u);
 
   ASSERT_TRUE(decos[0]->Is<ast::WorkgroupDecoration>());
-  auto values = decos[0]->As<ast::WorkgroupDecoration>()->values();
+  auto values = decos[0]->As<ast::WorkgroupDecoration>()->Values();
 
   ASSERT_NE(values[0], nullptr);
   auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(x_scalar, nullptr);
-  ASSERT_TRUE(x_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(x_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 2u);
+  ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
 
   ASSERT_NE(values[1], nullptr);
   auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(y_scalar, nullptr);
-  ASSERT_TRUE(y_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(y_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 3u);
+  ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 3u);
 
   ASSERT_NE(values[2], nullptr);
   auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(z_scalar, nullptr);
-  ASSERT_TRUE(z_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(z_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 4u);
+  ASSERT_TRUE(z_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(z_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
 
   ASSERT_TRUE(decos[1]->Is<ast::StageDecoration>());
-  EXPECT_EQ(decos[1]->As<ast::StageDecoration>()->value(),
+  EXPECT_EQ(decos[1]->As<ast::StageDecoration>()->stage,
             ast::PipelineStage::kCompute);
 
-  auto* body = f->body();
-  ASSERT_EQ(body->size(), 1u);
-  EXPECT_TRUE(body->get(0)->Is<ast::ReturnStatement>());
+  auto* body = f->body;
+  ASSERT_EQ(body->statements.size(), 1u);
+  EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
 }
 
 TEST_F(ParserImplTest, FunctionDecl_ReturnTypeDecorationList) {
@@ -211,23 +211,23 @@
   EXPECT_TRUE(f.matched);
   ASSERT_NE(f.value, nullptr);
 
-  EXPECT_EQ(f->symbol(), p->builder().Symbols().Get("main"));
-  ASSERT_NE(f->return_type(), nullptr);
-  EXPECT_TRUE(f->return_type()->Is<ast::F32>());
-  ASSERT_EQ(f->params().size(), 0u);
+  EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
+  ASSERT_NE(f->return_type, nullptr);
+  EXPECT_TRUE(f->return_type->Is<ast::F32>());
+  ASSERT_EQ(f->params.size(), 0u);
 
-  auto& decorations = f->decorations();
+  auto& decorations = f->decorations;
   EXPECT_EQ(decorations.size(), 0u);
 
-  auto& ret_type_decorations = f->return_type_decorations();
+  auto& ret_type_decorations = f->return_type_decorations;
   ASSERT_EQ(ret_type_decorations.size(), 1u);
   auto* loc = ret_type_decorations[0]->As<ast::LocationDecoration>();
   ASSERT_TRUE(loc != nullptr);
-  EXPECT_EQ(loc->value(), 1u);
+  EXPECT_EQ(loc->value, 1u);
 
-  auto* body = f->body();
-  ASSERT_EQ(body->size(), 1u);
-  EXPECT_TRUE(body->get(0)->Is<ast::ReturnStatement>());
+  auto* body = f->body;
+  ASSERT_EQ(body->statements.size(), 1u);
+  EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
 }
 
 TEST_F(ParserImplTest, FunctionDecl_InvalidHeader) {
diff --git a/src/reader/wgsl/parser_impl_function_decoration_list_test.cc b/src/reader/wgsl/parser_impl_function_decoration_list_test.cc
index 0b76ef2..dae3f9a 100644
--- a/src/reader/wgsl/parser_impl_function_decoration_list_test.cc
+++ b/src/reader/wgsl/parser_impl_function_decoration_list_test.cc
@@ -34,15 +34,15 @@
   ASSERT_NE(deco_1, nullptr);
 
   ASSERT_TRUE(deco_0->Is<ast::WorkgroupDecoration>());
-  ast::Expression* x = deco_0->As<ast::WorkgroupDecoration>()->values()[0];
+  ast::Expression* x = deco_0->As<ast::WorkgroupDecoration>()->x;
   ASSERT_NE(x, nullptr);
   auto* x_scalar = x->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(x_scalar, nullptr);
-  ASSERT_TRUE(x_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(x_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 2u);
+  ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 2u);
 
   ASSERT_TRUE(deco_1->Is<ast::StageDecoration>());
-  EXPECT_EQ(deco_1->As<ast::StageDecoration>()->value(),
+  EXPECT_EQ(deco_1->As<ast::StageDecoration>()->stage,
             ast::PipelineStage::kCompute);
 }
 
diff --git a/src/reader/wgsl/parser_impl_function_decoration_test.cc b/src/reader/wgsl/parser_impl_function_decoration_test.cc
index 432f99e..2fe6994 100644
--- a/src/reader/wgsl/parser_impl_function_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_function_decoration_test.cc
@@ -32,13 +32,13 @@
   ASSERT_NE(func_deco, nullptr);
   ASSERT_TRUE(func_deco->Is<ast::WorkgroupDecoration>());
 
-  auto values = func_deco->As<ast::WorkgroupDecoration>()->values();
+  auto values = func_deco->As<ast::WorkgroupDecoration>()->Values();
 
   ASSERT_NE(values[0], nullptr);
   auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(x_scalar, nullptr);
-  ASSERT_TRUE(x_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(x_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 4u);
+  ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
 
   EXPECT_EQ(values[1], nullptr);
   EXPECT_EQ(values[2], nullptr);
@@ -55,19 +55,19 @@
   ASSERT_NE(func_deco, nullptr) << p->error();
   ASSERT_TRUE(func_deco->Is<ast::WorkgroupDecoration>());
 
-  auto values = func_deco->As<ast::WorkgroupDecoration>()->values();
+  auto values = func_deco->As<ast::WorkgroupDecoration>()->Values();
 
   ASSERT_NE(values[0], nullptr);
   auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(x_scalar, nullptr);
-  ASSERT_TRUE(x_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(x_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 4u);
+  ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
 
   ASSERT_NE(values[1], nullptr);
   auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(y_scalar, nullptr);
-  ASSERT_TRUE(y_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(y_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 5u);
+  ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 5u);
 
   EXPECT_EQ(values[2], nullptr);
 }
@@ -83,25 +83,25 @@
   ASSERT_NE(func_deco, nullptr);
   ASSERT_TRUE(func_deco->Is<ast::WorkgroupDecoration>());
 
-  auto values = func_deco->As<ast::WorkgroupDecoration>()->values();
+  auto values = func_deco->As<ast::WorkgroupDecoration>()->Values();
 
   ASSERT_NE(values[0], nullptr);
   auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(x_scalar, nullptr);
-  ASSERT_TRUE(x_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(x_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 4u);
+  ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
 
   ASSERT_NE(values[1], nullptr);
   auto* y_scalar = values[1]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(y_scalar, nullptr);
-  ASSERT_TRUE(y_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(y_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 5u);
+  ASSERT_TRUE(y_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(y_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 5u);
 
   ASSERT_NE(values[2], nullptr);
   auto* z_scalar = values[2]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(z_scalar, nullptr);
-  ASSERT_TRUE(z_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(z_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 6u);
+  ASSERT_TRUE(z_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(z_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 6u);
 }
 
 TEST_F(ParserImplTest, Decoration_Workgroup_WithIdent) {
@@ -115,18 +115,18 @@
   ASSERT_NE(func_deco, nullptr);
   ASSERT_TRUE(func_deco->Is<ast::WorkgroupDecoration>());
 
-  auto values = func_deco->As<ast::WorkgroupDecoration>()->values();
+  auto values = func_deco->As<ast::WorkgroupDecoration>()->Values();
 
   ASSERT_NE(values[0], nullptr);
   auto* x_scalar = values[0]->As<ast::ScalarConstructorExpression>();
   ASSERT_NE(x_scalar, nullptr);
-  ASSERT_TRUE(x_scalar->literal()->Is<ast::IntLiteral>());
-  EXPECT_EQ(x_scalar->literal()->As<ast::IntLiteral>()->value_as_u32(), 4u);
+  ASSERT_TRUE(x_scalar->literal->Is<ast::IntLiteral>());
+  EXPECT_EQ(x_scalar->literal->As<ast::IntLiteral>()->ValueAsU32(), 4u);
 
   ASSERT_NE(values[1], nullptr);
   auto* y_ident = values[1]->As<ast::IdentifierExpression>();
   ASSERT_NE(y_ident, nullptr);
-  EXPECT_EQ(p->builder().Symbols().NameFor(y_ident->symbol()), "height");
+  EXPECT_EQ(p->builder().Symbols().NameFor(y_ident->symbol), "height");
 
   ASSERT_EQ(values[2], nullptr);
 }
@@ -231,7 +231,7 @@
   auto* func_deco = deco.value->As<ast::Decoration>();
   ASSERT_NE(func_deco, nullptr);
   ASSERT_TRUE(func_deco->Is<ast::StageDecoration>());
-  EXPECT_EQ(func_deco->As<ast::StageDecoration>()->value(),
+  EXPECT_EQ(func_deco->As<ast::StageDecoration>()->stage,
             ast::PipelineStage::kCompute);
 }
 
diff --git a/src/reader/wgsl/parser_impl_function_header_test.cc b/src/reader/wgsl/parser_impl_function_header_test.cc
index b3f38c8..b17581e 100644
--- a/src/reader/wgsl/parser_impl_function_header_test.cc
+++ b/src/reader/wgsl/parser_impl_function_header_test.cc
@@ -28,8 +28,8 @@
 
   EXPECT_EQ(f->name, "main");
   ASSERT_EQ(f->params.size(), 2u);
-  EXPECT_EQ(f->params[0]->symbol(), p->builder().Symbols().Get("a"));
-  EXPECT_EQ(f->params[1]->symbol(), p->builder().Symbols().Get("b"));
+  EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get("a"));
+  EXPECT_EQ(f->params[1]->symbol, p->builder().Symbols().Get("b"));
   EXPECT_TRUE(f->return_type->Is<ast::Void>());
 }
 
@@ -41,7 +41,7 @@
 
   EXPECT_EQ(f->name, "main");
   ASSERT_EQ(f->params.size(), 1u);
-  EXPECT_EQ(f->params[0]->symbol(), p->builder().Symbols().Get("a"));
+  EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get("a"));
   EXPECT_TRUE(f->return_type->Is<ast::Void>());
 }
 
@@ -58,7 +58,7 @@
   ASSERT_EQ(f->return_type_decorations.size(), 1u);
   auto* loc = f->return_type_decorations[0]->As<ast::LocationDecoration>();
   ASSERT_TRUE(loc != nullptr);
-  EXPECT_EQ(loc->value(), 1u);
+  EXPECT_EQ(loc->value, 1u);
 }
 
 TEST_F(ParserImplTest, FunctionHeader_InvariantReturnType) {
@@ -87,13 +87,13 @@
   ASSERT_EQ(f->return_type_decorations.size(), 1u);
   auto* loc = f->return_type_decorations[0]->As<ast::LocationDecoration>();
   ASSERT_TRUE(loc != nullptr);
-  EXPECT_EQ(loc->value(), 1u);
+  EXPECT_EQ(loc->value, 1u);
 
   auto* array_type = f->return_type->As<ast::Array>();
-  ASSERT_EQ(array_type->decorations().size(), 1u);
-  auto* stride = array_type->decorations()[0]->As<ast::StrideDecoration>();
+  ASSERT_EQ(array_type->decorations.size(), 1u);
+  auto* stride = array_type->decorations[0]->As<ast::StrideDecoration>();
   ASSERT_TRUE(stride != nullptr);
-  EXPECT_EQ(stride->stride(), 16u);
+  EXPECT_EQ(stride->stride, 16u);
 }
 
 TEST_F(ParserImplTest, FunctionHeader_MissingIdent) {
diff --git a/src/reader/wgsl/parser_impl_global_constant_decl_test.cc b/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
index df4bf98..308bd70 100644
--- a/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_global_constant_decl_test.cc
@@ -31,21 +31,21 @@
   EXPECT_FALSE(e.errored);
   ASSERT_NE(e.value, nullptr);
 
-  EXPECT_TRUE(e->is_const());
-  EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
-  ASSERT_NE(e->type(), nullptr);
-  EXPECT_TRUE(e->type()->Is<ast::F32>());
+  EXPECT_TRUE(e->is_const);
+  EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
+  ASSERT_NE(e->type, nullptr);
+  EXPECT_TRUE(e->type->Is<ast::F32>());
 
-  EXPECT_EQ(e->source().range.begin.line, 1u);
-  EXPECT_EQ(e->source().range.begin.column, 5u);
-  EXPECT_EQ(e->source().range.end.line, 1u);
-  EXPECT_EQ(e->source().range.end.column, 6u);
+  EXPECT_EQ(e->source.range.begin.line, 1u);
+  EXPECT_EQ(e->source.range.begin.column, 5u);
+  EXPECT_EQ(e->source.range.end.line, 1u);
+  EXPECT_EQ(e->source.range.end.column, 6u);
 
-  ASSERT_NE(e->constructor(), nullptr);
-  EXPECT_TRUE(e->constructor()->Is<ast::ConstructorExpression>());
+  ASSERT_NE(e->constructor, nullptr);
+  EXPECT_TRUE(e->constructor->Is<ast::ConstructorExpression>());
 
   EXPECT_FALSE(
-      ast::HasDecoration<ast::OverrideDecoration>(e.value->decorations()));
+      ast::HasDecoration<ast::OverrideDecoration>(e.value->decorations));
 }
 
 TEST_F(ParserImplTest, GlobalConstantDecl_Inferred) {
@@ -59,20 +59,20 @@
   EXPECT_FALSE(e.errored);
   ASSERT_NE(e.value, nullptr);
 
-  EXPECT_TRUE(e->is_const());
-  EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
-  EXPECT_EQ(e->type(), nullptr);
+  EXPECT_TRUE(e->is_const);
+  EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
+  EXPECT_EQ(e->type, nullptr);
 
-  EXPECT_EQ(e->source().range.begin.line, 1u);
-  EXPECT_EQ(e->source().range.begin.column, 5u);
-  EXPECT_EQ(e->source().range.end.line, 1u);
-  EXPECT_EQ(e->source().range.end.column, 6u);
+  EXPECT_EQ(e->source.range.begin.line, 1u);
+  EXPECT_EQ(e->source.range.begin.column, 5u);
+  EXPECT_EQ(e->source.range.end.line, 1u);
+  EXPECT_EQ(e->source.range.end.column, 6u);
 
-  ASSERT_NE(e->constructor(), nullptr);
-  EXPECT_TRUE(e->constructor()->Is<ast::ConstructorExpression>());
+  ASSERT_NE(e->constructor, nullptr);
+  EXPECT_TRUE(e->constructor->Is<ast::ConstructorExpression>());
 
   EXPECT_FALSE(
-      ast::HasDecoration<ast::OverrideDecoration>(e.value->decorations()));
+      ast::HasDecoration<ast::OverrideDecoration>(e.value->decorations));
 }
 
 TEST_F(ParserImplTest, GlobalConstantDecl_InvalidVariable) {
@@ -126,24 +126,24 @@
   EXPECT_FALSE(e.errored);
   ASSERT_NE(e.value, nullptr);
 
-  EXPECT_TRUE(e->is_const());
-  EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
-  ASSERT_NE(e->type(), nullptr);
-  EXPECT_TRUE(e->type()->Is<ast::F32>());
+  EXPECT_TRUE(e->is_const);
+  EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
+  ASSERT_NE(e->type, nullptr);
+  EXPECT_TRUE(e->type->Is<ast::F32>());
 
-  EXPECT_EQ(e->source().range.begin.line, 1u);
-  EXPECT_EQ(e->source().range.begin.column, 21u);
-  EXPECT_EQ(e->source().range.end.line, 1u);
-  EXPECT_EQ(e->source().range.end.column, 22u);
+  EXPECT_EQ(e->source.range.begin.line, 1u);
+  EXPECT_EQ(e->source.range.begin.column, 21u);
+  EXPECT_EQ(e->source.range.end.line, 1u);
+  EXPECT_EQ(e->source.range.end.column, 22u);
 
-  ASSERT_NE(e->constructor(), nullptr);
-  EXPECT_TRUE(e->constructor()->Is<ast::ConstructorExpression>());
+  ASSERT_NE(e->constructor, nullptr);
+  EXPECT_TRUE(e->constructor->Is<ast::ConstructorExpression>());
 
   auto* override_deco =
-      ast::GetDecoration<ast::OverrideDecoration>(e.value->decorations());
+      ast::GetDecoration<ast::OverrideDecoration>(e.value->decorations);
   ASSERT_NE(override_deco, nullptr);
-  EXPECT_TRUE(override_deco->HasValue());
-  EXPECT_EQ(override_deco->value(), 7u);
+  EXPECT_TRUE(override_deco->has_value);
+  EXPECT_EQ(override_deco->value, 7u);
 }
 
 TEST_F(ParserImplTest, GlobalConstantDec_Override_WithoutId) {
@@ -158,23 +158,23 @@
   EXPECT_FALSE(e.errored);
   ASSERT_NE(e.value, nullptr);
 
-  EXPECT_TRUE(e->is_const());
-  EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
-  ASSERT_NE(e->type(), nullptr);
-  EXPECT_TRUE(e->type()->Is<ast::F32>());
+  EXPECT_TRUE(e->is_const);
+  EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
+  ASSERT_NE(e->type, nullptr);
+  EXPECT_TRUE(e->type->Is<ast::F32>());
 
-  EXPECT_EQ(e->source().range.begin.line, 1u);
-  EXPECT_EQ(e->source().range.begin.column, 18u);
-  EXPECT_EQ(e->source().range.end.line, 1u);
-  EXPECT_EQ(e->source().range.end.column, 19u);
+  EXPECT_EQ(e->source.range.begin.line, 1u);
+  EXPECT_EQ(e->source.range.begin.column, 18u);
+  EXPECT_EQ(e->source.range.end.line, 1u);
+  EXPECT_EQ(e->source.range.end.column, 19u);
 
-  ASSERT_NE(e->constructor(), nullptr);
-  EXPECT_TRUE(e->constructor()->Is<ast::ConstructorExpression>());
+  ASSERT_NE(e->constructor, nullptr);
+  EXPECT_TRUE(e->constructor->Is<ast::ConstructorExpression>());
 
   auto* override_deco =
-      ast::GetDecoration<ast::OverrideDecoration>(e.value->decorations());
+      ast::GetDecoration<ast::OverrideDecoration>(e.value->decorations);
   ASSERT_NE(override_deco, nullptr);
-  EXPECT_FALSE(override_deco->HasValue());
+  EXPECT_FALSE(override_deco->has_value);
 }
 
 TEST_F(ParserImplTest, GlobalConstantDec_Override_MissingId) {
diff --git a/src/reader/wgsl/parser_impl_global_decl_test.cc b/src/reader/wgsl/parser_impl_global_decl_test.cc
index ef7caff..8489fe6 100644
--- a/src/reader/wgsl/parser_impl_global_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_global_decl_test.cc
@@ -34,7 +34,7 @@
   ASSERT_EQ(program.AST().GlobalVariables().size(), 1u);
 
   auto* v = program.AST().GlobalVariables()[0];
-  EXPECT_EQ(v->symbol(), program.Symbols().Get("a"));
+  EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
 }
 
 TEST_F(ParserImplTest, GlobalDecl_GlobalVariable_Inferred_Invalid) {
@@ -67,7 +67,7 @@
   ASSERT_EQ(program.AST().GlobalVariables().size(), 1u);
 
   auto* v = program.AST().GlobalVariables()[0];
-  EXPECT_EQ(v->symbol(), program.Symbols().Get("a"));
+  EXPECT_EQ(v->symbol, program.Symbols().Get("a"));
 }
 
 TEST_F(ParserImplTest, GlobalDecl_GlobalConstant_Invalid) {
@@ -93,7 +93,7 @@
   ASSERT_EQ(program.AST().TypeDecls().size(), 1u);
   ASSERT_TRUE(program.AST().TypeDecls()[0]->Is<ast::Alias>());
   EXPECT_EQ(program.Symbols().NameFor(
-                program.AST().TypeDecls()[0]->As<ast::Alias>()->symbol()),
+                program.AST().TypeDecls()[0]->As<ast::Alias>()->name),
             "A");
 }
 
@@ -110,14 +110,14 @@
   ASSERT_EQ(program.AST().TypeDecls().size(), 2u);
   ASSERT_TRUE(program.AST().TypeDecls()[0]->Is<ast::Struct>());
   auto* str = program.AST().TypeDecls()[0]->As<ast::Struct>();
-  EXPECT_EQ(str->name(), program.Symbols().Get("A"));
+  EXPECT_EQ(str->name, program.Symbols().Get("A"));
 
   ASSERT_TRUE(program.AST().TypeDecls()[1]->Is<ast::Alias>());
   auto* alias = program.AST().TypeDecls()[1]->As<ast::Alias>();
-  EXPECT_EQ(alias->symbol(), program.Symbols().Get("B"));
-  auto* tn = alias->type()->As<ast::TypeName>();
+  EXPECT_EQ(alias->name, program.Symbols().Get("B"));
+  auto* tn = alias->type->As<ast::TypeName>();
   EXPECT_NE(tn, nullptr);
-  EXPECT_EQ(tn->name(), str->name());
+  EXPECT_EQ(tn->name, str->name);
 }
 
 TEST_F(ParserImplTest, GlobalDecl_TypeAlias_Invalid) {
@@ -141,7 +141,7 @@
 
   auto program = p->program();
   ASSERT_EQ(program.AST().Functions().size(), 1u);
-  EXPECT_EQ(program.Symbols().NameFor(program.AST().Functions()[0]->symbol()),
+  EXPECT_EQ(program.Symbols().NameFor(program.AST().Functions()[0]->symbol),
             "main");
 }
 
@@ -152,7 +152,7 @@
 
   auto program = p->program();
   ASSERT_EQ(program.AST().Functions().size(), 1u);
-  EXPECT_EQ(program.Symbols().NameFor(program.AST().Functions()[0]->symbol()),
+  EXPECT_EQ(program.Symbols().NameFor(program.AST().Functions()[0]->symbol),
             "main");
 }
 
@@ -176,8 +176,8 @@
   ASSERT_TRUE(t->Is<ast::Struct>());
 
   auto* str = t->As<ast::Struct>();
-  EXPECT_EQ(str->name(), program.Symbols().Get("A"));
-  EXPECT_EQ(str->members().size(), 2u);
+  EXPECT_EQ(str->name, program.Symbols().Get("A"));
+  EXPECT_EQ(str->members.size(), 2u);
 }
 
 TEST_F(ParserImplTest, GlobalDecl_Struct_WithStride) {
@@ -194,18 +194,18 @@
   ASSERT_TRUE(t->Is<ast::Struct>());
 
   auto* str = t->As<ast::Struct>();
-  EXPECT_EQ(str->name(), program.Symbols().Get("A"));
-  EXPECT_EQ(str->members().size(), 1u);
+  EXPECT_EQ(str->name, program.Symbols().Get("A"));
+  EXPECT_EQ(str->members.size(), 1u);
   EXPECT_FALSE(str->IsBlockDecorated());
 
-  const auto* ty = str->members()[0]->type();
+  const auto* ty = str->members[0]->type;
   ASSERT_TRUE(ty->Is<ast::Array>());
   const auto* arr = ty->As<ast::Array>();
 
-  ASSERT_EQ(arr->decorations().size(), 1u);
-  auto* stride = arr->decorations()[0];
+  ASSERT_EQ(arr->decorations.size(), 1u);
+  auto* stride = arr->decorations[0];
   ASSERT_TRUE(stride->Is<ast::StrideDecoration>());
-  ASSERT_EQ(stride->As<ast::StrideDecoration>()->stride(), 4u);
+  ASSERT_EQ(stride->As<ast::StrideDecoration>()->stride, 4u);
 }
 
 TEST_F(ParserImplTest, GlobalDecl_Struct_WithDecoration) {
@@ -221,8 +221,8 @@
   ASSERT_TRUE(t->Is<ast::Struct>());
 
   auto* str = t->As<ast::Struct>();
-  EXPECT_EQ(str->name(), program.Symbols().Get("A"));
-  EXPECT_EQ(str->members().size(), 1u);
+  EXPECT_EQ(str->name, program.Symbols().Get("A"));
+  EXPECT_EQ(str->members.size(), 1u);
   EXPECT_TRUE(str->IsBlockDecorated());
 }
 
diff --git a/src/reader/wgsl/parser_impl_global_variable_decl_test.cc b/src/reader/wgsl/parser_impl_global_variable_decl_test.cc
index ba6b115..c7c5630 100644
--- a/src/reader/wgsl/parser_impl_global_variable_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_global_variable_decl_test.cc
@@ -30,16 +30,16 @@
   EXPECT_FALSE(e.errored);
   ASSERT_NE(e.value, nullptr);
 
-  EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
-  EXPECT_TRUE(e->type()->Is<ast::F32>());
-  EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kPrivate);
+  EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
+  EXPECT_TRUE(e->type->Is<ast::F32>());
+  EXPECT_EQ(e->declared_storage_class, ast::StorageClass::kPrivate);
 
-  EXPECT_EQ(e->source().range.begin.line, 1u);
-  EXPECT_EQ(e->source().range.begin.column, 14u);
-  EXPECT_EQ(e->source().range.end.line, 1u);
-  EXPECT_EQ(e->source().range.end.column, 15u);
+  EXPECT_EQ(e->source.range.begin.line, 1u);
+  EXPECT_EQ(e->source.range.begin.column, 14u);
+  EXPECT_EQ(e->source.range.end.line, 1u);
+  EXPECT_EQ(e->source.range.end.column, 15u);
 
-  ASSERT_EQ(e->constructor(), nullptr);
+  ASSERT_EQ(e->constructor, nullptr);
 }
 
 TEST_F(ParserImplTest, GlobalVariableDecl_WithConstructor) {
@@ -53,18 +53,18 @@
   EXPECT_FALSE(e.errored);
   ASSERT_NE(e.value, nullptr);
 
-  EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
-  EXPECT_TRUE(e->type()->Is<ast::F32>());
-  EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kPrivate);
+  EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
+  EXPECT_TRUE(e->type->Is<ast::F32>());
+  EXPECT_EQ(e->declared_storage_class, ast::StorageClass::kPrivate);
 
-  EXPECT_EQ(e->source().range.begin.line, 1u);
-  EXPECT_EQ(e->source().range.begin.column, 14u);
-  EXPECT_EQ(e->source().range.end.line, 1u);
-  EXPECT_EQ(e->source().range.end.column, 15u);
+  EXPECT_EQ(e->source.range.begin.line, 1u);
+  EXPECT_EQ(e->source.range.begin.column, 14u);
+  EXPECT_EQ(e->source.range.end.line, 1u);
+  EXPECT_EQ(e->source.range.end.column, 15u);
 
-  ASSERT_NE(e->constructor(), nullptr);
-  ASSERT_TRUE(e->constructor()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(e->constructor()->Is<ast::ScalarConstructorExpression>());
+  ASSERT_NE(e->constructor, nullptr);
+  ASSERT_TRUE(e->constructor->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(e->constructor->Is<ast::ScalarConstructorExpression>());
 }
 
 TEST_F(ParserImplTest, GlobalVariableDecl_WithDecoration) {
@@ -78,19 +78,19 @@
   EXPECT_FALSE(e.errored);
   ASSERT_NE(e.value, nullptr);
 
-  EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
-  ASSERT_NE(e->type(), nullptr);
-  EXPECT_TRUE(e->type()->Is<ast::F32>());
-  EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kUniform);
+  EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
+  ASSERT_NE(e->type, nullptr);
+  EXPECT_TRUE(e->type->Is<ast::F32>());
+  EXPECT_EQ(e->declared_storage_class, ast::StorageClass::kUniform);
 
-  EXPECT_EQ(e->source().range.begin.line, 1u);
-  EXPECT_EQ(e->source().range.begin.column, 39u);
-  EXPECT_EQ(e->source().range.end.line, 1u);
-  EXPECT_EQ(e->source().range.end.column, 40u);
+  EXPECT_EQ(e->source.range.begin.line, 1u);
+  EXPECT_EQ(e->source.range.begin.column, 39u);
+  EXPECT_EQ(e->source.range.end.line, 1u);
+  EXPECT_EQ(e->source.range.end.column, 40u);
 
-  ASSERT_EQ(e->constructor(), nullptr);
+  ASSERT_EQ(e->constructor, nullptr);
 
-  auto& decorations = e->decorations();
+  auto& decorations = e->decorations;
   ASSERT_EQ(decorations.size(), 2u);
   ASSERT_TRUE(decorations[0]->Is<ast::BindingDecoration>());
   ASSERT_TRUE(decorations[1]->Is<ast::GroupDecoration>());
@@ -108,19 +108,19 @@
   EXPECT_FALSE(e.errored);
   ASSERT_NE(e.value, nullptr);
 
-  EXPECT_EQ(e->symbol(), p->builder().Symbols().Get("a"));
-  ASSERT_NE(e->type(), nullptr);
-  EXPECT_TRUE(e->type()->Is<ast::F32>());
-  EXPECT_EQ(e->declared_storage_class(), ast::StorageClass::kUniform);
+  EXPECT_EQ(e->symbol, p->builder().Symbols().Get("a"));
+  ASSERT_NE(e->type, nullptr);
+  EXPECT_TRUE(e->type->Is<ast::F32>());
+  EXPECT_EQ(e->declared_storage_class, ast::StorageClass::kUniform);
 
-  EXPECT_EQ(e->source().range.begin.line, 1u);
-  EXPECT_EQ(e->source().range.begin.column, 42u);
-  EXPECT_EQ(e->source().range.end.line, 1u);
-  EXPECT_EQ(e->source().range.end.column, 43u);
+  EXPECT_EQ(e->source.range.begin.line, 1u);
+  EXPECT_EQ(e->source.range.begin.column, 42u);
+  EXPECT_EQ(e->source.range.end.line, 1u);
+  EXPECT_EQ(e->source.range.end.column, 43u);
 
-  ASSERT_EQ(e->constructor(), nullptr);
+  ASSERT_EQ(e->constructor, nullptr);
 
-  auto& decorations = e->decorations();
+  auto& decorations = e->decorations;
   ASSERT_EQ(decorations.size(), 2u);
   ASSERT_TRUE(decorations[0]->Is<ast::BindingDecoration>());
   ASSERT_TRUE(decorations[1]->Is<ast::GroupDecoration>());
diff --git a/src/reader/wgsl/parser_impl_if_stmt_test.cc b/src/reader/wgsl/parser_impl_if_stmt_test.cc
index fdee7c8..1c93c19 100644
--- a/src/reader/wgsl/parser_impl_if_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_if_stmt_test.cc
@@ -28,10 +28,10 @@
   ASSERT_NE(e.value, nullptr);
 
   ASSERT_TRUE(e->Is<ast::IfStatement>());
-  ASSERT_NE(e->condition(), nullptr);
-  ASSERT_TRUE(e->condition()->Is<ast::BinaryExpression>());
-  EXPECT_EQ(e->body()->size(), 2u);
-  EXPECT_EQ(e->else_statements().size(), 0u);
+  ASSERT_NE(e->condition, nullptr);
+  ASSERT_TRUE(e->condition->Is<ast::BinaryExpression>());
+  EXPECT_EQ(e->body->statements.size(), 2u);
+  EXPECT_EQ(e->else_statements.size(), 0u);
 }
 
 TEST_F(ParserImplTest, IfStmt_WithElse) {
@@ -43,18 +43,18 @@
   ASSERT_NE(e.value, nullptr);
 
   ASSERT_TRUE(e->Is<ast::IfStatement>());
-  ASSERT_NE(e->condition(), nullptr);
-  ASSERT_TRUE(e->condition()->Is<ast::BinaryExpression>());
-  EXPECT_EQ(e->body()->size(), 2u);
+  ASSERT_NE(e->condition, nullptr);
+  ASSERT_TRUE(e->condition->Is<ast::BinaryExpression>());
+  EXPECT_EQ(e->body->statements.size(), 2u);
 
-  ASSERT_EQ(e->else_statements().size(), 2u);
-  ASSERT_NE(e->else_statements()[0]->condition(), nullptr);
+  ASSERT_EQ(e->else_statements.size(), 2u);
+  ASSERT_NE(e->else_statements[0]->condition, nullptr);
   ASSERT_TRUE(
-      e->else_statements()[0]->condition()->Is<ast::IdentifierExpression>());
-  EXPECT_EQ(e->else_statements()[0]->body()->size(), 1u);
+      e->else_statements[0]->condition->Is<ast::IdentifierExpression>());
+  EXPECT_EQ(e->else_statements[0]->body->statements.size(), 1u);
 
-  ASSERT_EQ(e->else_statements()[1]->condition(), nullptr);
-  EXPECT_EQ(e->else_statements()[1]->body()->size(), 0u);
+  ASSERT_EQ(e->else_statements[1]->condition, nullptr);
+  EXPECT_EQ(e->else_statements[1]->body->statements.size(), 0u);
 }
 
 TEST_F(ParserImplTest, IfStmt_InvalidCondition) {
diff --git a/src/reader/wgsl/parser_impl_inclusive_or_expression_test.cc b/src/reader/wgsl/parser_impl_inclusive_or_expression_test.cc
index 8fee841..15b04aa 100644
--- a/src/reader/wgsl/parser_impl_inclusive_or_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_inclusive_or_expression_test.cc
@@ -29,17 +29,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kOr, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kOr, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, InclusiveOrExpression_InvalidLHS) {
diff --git a/src/reader/wgsl/parser_impl_logical_and_expression_test.cc b/src/reader/wgsl/parser_impl_logical_and_expression_test.cc
index f987321..c2bbb2b 100644
--- a/src/reader/wgsl/parser_impl_logical_and_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_logical_and_expression_test.cc
@@ -29,17 +29,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kLogicalAnd, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kLogicalAnd, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, LogicalAndExpression_InvalidLHS) {
diff --git a/src/reader/wgsl/parser_impl_logical_or_expression_test.cc b/src/reader/wgsl/parser_impl_logical_or_expression_test.cc
index aa1e094..320bad6 100644
--- a/src/reader/wgsl/parser_impl_logical_or_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_logical_or_expression_test.cc
@@ -29,17 +29,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kLogicalOr, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kLogicalOr, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, LogicalOrExpression_InvalidLHS) {
diff --git a/src/reader/wgsl/parser_impl_loop_stmt_test.cc b/src/reader/wgsl/parser_impl_loop_stmt_test.cc
index b55aa91..4da4962 100644
--- a/src/reader/wgsl/parser_impl_loop_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_loop_stmt_test.cc
@@ -28,10 +28,10 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
 
-  ASSERT_EQ(e->body()->size(), 1u);
-  EXPECT_TRUE(e->body()->get(0)->Is<ast::DiscardStatement>());
+  ASSERT_EQ(e->body->statements.size(), 1u);
+  EXPECT_TRUE(e->body->statements[0]->Is<ast::DiscardStatement>());
 
-  EXPECT_EQ(e->continuing()->size(), 0u);
+  EXPECT_EQ(e->continuing->statements.size(), 0u);
 }
 
 TEST_F(ParserImplTest, LoopStmt_BodyWithContinuing) {
@@ -42,11 +42,11 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
 
-  ASSERT_EQ(e->body()->size(), 1u);
-  EXPECT_TRUE(e->body()->get(0)->Is<ast::DiscardStatement>());
+  ASSERT_EQ(e->body->statements.size(), 1u);
+  EXPECT_TRUE(e->body->statements[0]->Is<ast::DiscardStatement>());
 
-  EXPECT_EQ(e->continuing()->size(), 1u);
-  EXPECT_TRUE(e->continuing()->get(0)->Is<ast::DiscardStatement>());
+  EXPECT_EQ(e->continuing->statements.size(), 1u);
+  EXPECT_TRUE(e->continuing->statements[0]->Is<ast::DiscardStatement>());
 }
 
 TEST_F(ParserImplTest, LoopStmt_NoBodyNoContinuing) {
@@ -56,8 +56,8 @@
   EXPECT_FALSE(e.errored);
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
-  ASSERT_EQ(e->body()->size(), 0u);
-  ASSERT_EQ(e->continuing()->size(), 0u);
+  ASSERT_EQ(e->body->statements.size(), 0u);
+  ASSERT_EQ(e->continuing->statements.size(), 0u);
 }
 
 TEST_F(ParserImplTest, LoopStmt_NoBodyWithContinuing) {
@@ -67,9 +67,9 @@
   EXPECT_FALSE(e.errored);
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
-  ASSERT_EQ(e->body()->size(), 0u);
-  ASSERT_EQ(e->continuing()->size(), 1u);
-  EXPECT_TRUE(e->continuing()->get(0)->Is<ast::DiscardStatement>());
+  ASSERT_EQ(e->body->statements.size(), 0u);
+  ASSERT_EQ(e->continuing->statements.size(), 1u);
+  EXPECT_TRUE(e->continuing->statements[0]->Is<ast::DiscardStatement>());
 }
 
 TEST_F(ParserImplTest, LoopStmt_MissingBracketLeft) {
diff --git a/src/reader/wgsl/parser_impl_multiplicative_expression_test.cc b/src/reader/wgsl/parser_impl_multiplicative_expression_test.cc
index 05a3b76..ad86047 100644
--- a/src/reader/wgsl/parser_impl_multiplicative_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_multiplicative_expression_test.cc
@@ -29,17 +29,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
@@ -52,17 +52,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kDivide, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kDivide, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
@@ -75,17 +75,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kModulo, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kModulo, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, MultiplicativeExpression_InvalidLHS) {
diff --git a/src/reader/wgsl/parser_impl_param_list_test.cc b/src/reader/wgsl/parser_impl_param_list_test.cc
index 4713462..e29725fc 100644
--- a/src/reader/wgsl/parser_impl_param_list_test.cc
+++ b/src/reader/wgsl/parser_impl_param_list_test.cc
@@ -27,14 +27,14 @@
   ASSERT_FALSE(e.errored);
   EXPECT_EQ(e.value.size(), 1u);
 
-  EXPECT_EQ(e.value[0]->symbol(), p->builder().Symbols().Get("a"));
-  EXPECT_TRUE(e.value[0]->type()->Is<ast::I32>());
-  EXPECT_TRUE(e.value[0]->is_const());
+  EXPECT_EQ(e.value[0]->symbol, p->builder().Symbols().Get("a"));
+  EXPECT_TRUE(e.value[0]->type->Is<ast::I32>());
+  EXPECT_TRUE(e.value[0]->is_const);
 
-  ASSERT_EQ(e.value[0]->source().range.begin.line, 1u);
-  ASSERT_EQ(e.value[0]->source().range.begin.column, 1u);
-  ASSERT_EQ(e.value[0]->source().range.end.line, 1u);
-  ASSERT_EQ(e.value[0]->source().range.end.column, 2u);
+  ASSERT_EQ(e.value[0]->source.range.begin.line, 1u);
+  ASSERT_EQ(e.value[0]->source.range.begin.column, 1u);
+  ASSERT_EQ(e.value[0]->source.range.end.line, 1u);
+  ASSERT_EQ(e.value[0]->source.range.end.column, 2u);
 }
 
 TEST_F(ParserImplTest, ParamList_Multiple) {
@@ -45,34 +45,34 @@
   ASSERT_FALSE(e.errored);
   EXPECT_EQ(e.value.size(), 3u);
 
-  EXPECT_EQ(e.value[0]->symbol(), p->builder().Symbols().Get("a"));
-  EXPECT_TRUE(e.value[0]->type()->Is<ast::I32>());
-  EXPECT_TRUE(e.value[0]->is_const());
+  EXPECT_EQ(e.value[0]->symbol, p->builder().Symbols().Get("a"));
+  EXPECT_TRUE(e.value[0]->type->Is<ast::I32>());
+  EXPECT_TRUE(e.value[0]->is_const);
 
-  ASSERT_EQ(e.value[0]->source().range.begin.line, 1u);
-  ASSERT_EQ(e.value[0]->source().range.begin.column, 1u);
-  ASSERT_EQ(e.value[0]->source().range.end.line, 1u);
-  ASSERT_EQ(e.value[0]->source().range.end.column, 2u);
+  ASSERT_EQ(e.value[0]->source.range.begin.line, 1u);
+  ASSERT_EQ(e.value[0]->source.range.begin.column, 1u);
+  ASSERT_EQ(e.value[0]->source.range.end.line, 1u);
+  ASSERT_EQ(e.value[0]->source.range.end.column, 2u);
 
-  EXPECT_EQ(e.value[1]->symbol(), p->builder().Symbols().Get("b"));
-  EXPECT_TRUE(e.value[1]->type()->Is<ast::F32>());
-  EXPECT_TRUE(e.value[1]->is_const());
+  EXPECT_EQ(e.value[1]->symbol, p->builder().Symbols().Get("b"));
+  EXPECT_TRUE(e.value[1]->type->Is<ast::F32>());
+  EXPECT_TRUE(e.value[1]->is_const);
 
-  ASSERT_EQ(e.value[1]->source().range.begin.line, 1u);
-  ASSERT_EQ(e.value[1]->source().range.begin.column, 10u);
-  ASSERT_EQ(e.value[1]->source().range.end.line, 1u);
-  ASSERT_EQ(e.value[1]->source().range.end.column, 11u);
+  ASSERT_EQ(e.value[1]->source.range.begin.line, 1u);
+  ASSERT_EQ(e.value[1]->source.range.begin.column, 10u);
+  ASSERT_EQ(e.value[1]->source.range.end.line, 1u);
+  ASSERT_EQ(e.value[1]->source.range.end.column, 11u);
 
-  EXPECT_EQ(e.value[2]->symbol(), p->builder().Symbols().Get("c"));
-  ASSERT_TRUE(e.value[2]->type()->Is<ast::Vector>());
-  ASSERT_TRUE(e.value[2]->type()->As<ast::Vector>()->type()->Is<ast::F32>());
-  EXPECT_EQ(e.value[2]->type()->As<ast::Vector>()->size(), 2u);
-  EXPECT_TRUE(e.value[2]->is_const());
+  EXPECT_EQ(e.value[2]->symbol, p->builder().Symbols().Get("c"));
+  ASSERT_TRUE(e.value[2]->type->Is<ast::Vector>());
+  ASSERT_TRUE(e.value[2]->type->As<ast::Vector>()->type->Is<ast::F32>());
+  EXPECT_EQ(e.value[2]->type->As<ast::Vector>()->width, 2u);
+  EXPECT_TRUE(e.value[2]->is_const);
 
-  ASSERT_EQ(e.value[2]->source().range.begin.line, 1u);
-  ASSERT_EQ(e.value[2]->source().range.begin.column, 18u);
-  ASSERT_EQ(e.value[2]->source().range.end.line, 1u);
-  ASSERT_EQ(e.value[2]->source().range.end.column, 19u);
+  ASSERT_EQ(e.value[2]->source.range.begin.line, 1u);
+  ASSERT_EQ(e.value[2]->source.range.begin.column, 18u);
+  ASSERT_EQ(e.value[2]->source.range.end.line, 1u);
+  ASSERT_EQ(e.value[2]->source.range.end.column, 19u);
 }
 
 TEST_F(ParserImplTest, ParamList_Empty) {
@@ -101,34 +101,34 @@
   ASSERT_FALSE(e.errored);
   ASSERT_EQ(e.value.size(), 2u);
 
-  EXPECT_EQ(e.value[0]->symbol(), p->builder().Symbols().Get("coord"));
-  ASSERT_TRUE(e.value[0]->type()->Is<ast::Vector>());
-  EXPECT_TRUE(e.value[0]->type()->As<ast::Vector>()->type()->Is<ast::F32>());
-  EXPECT_EQ(e.value[0]->type()->As<ast::Vector>()->size(), 4u);
-  EXPECT_TRUE(e.value[0]->is_const());
-  auto decos0 = e.value[0]->decorations();
+  EXPECT_EQ(e.value[0]->symbol, p->builder().Symbols().Get("coord"));
+  ASSERT_TRUE(e.value[0]->type->Is<ast::Vector>());
+  EXPECT_TRUE(e.value[0]->type->As<ast::Vector>()->type->Is<ast::F32>());
+  EXPECT_EQ(e.value[0]->type->As<ast::Vector>()->width, 4u);
+  EXPECT_TRUE(e.value[0]->is_const);
+  auto decos0 = e.value[0]->decorations;
   ASSERT_EQ(decos0.size(), 1u);
   EXPECT_TRUE(decos0[0]->Is<ast::BuiltinDecoration>());
-  EXPECT_EQ(decos0[0]->As<ast::BuiltinDecoration>()->value(),
+  EXPECT_EQ(decos0[0]->As<ast::BuiltinDecoration>()->builtin,
             ast::Builtin::kPosition);
 
-  ASSERT_EQ(e.value[0]->source().range.begin.line, 1u);
-  ASSERT_EQ(e.value[0]->source().range.begin.column, 23u);
-  ASSERT_EQ(e.value[0]->source().range.end.line, 1u);
-  ASSERT_EQ(e.value[0]->source().range.end.column, 28u);
+  ASSERT_EQ(e.value[0]->source.range.begin.line, 1u);
+  ASSERT_EQ(e.value[0]->source.range.begin.column, 23u);
+  ASSERT_EQ(e.value[0]->source.range.end.line, 1u);
+  ASSERT_EQ(e.value[0]->source.range.end.column, 28u);
 
-  EXPECT_EQ(e.value[1]->symbol(), p->builder().Symbols().Get("loc1"));
-  EXPECT_TRUE(e.value[1]->type()->Is<ast::F32>());
-  EXPECT_TRUE(e.value[1]->is_const());
-  auto decos1 = e.value[1]->decorations();
+  EXPECT_EQ(e.value[1]->symbol, p->builder().Symbols().Get("loc1"));
+  EXPECT_TRUE(e.value[1]->type->Is<ast::F32>());
+  EXPECT_TRUE(e.value[1]->is_const);
+  auto decos1 = e.value[1]->decorations;
   ASSERT_EQ(decos1.size(), 1u);
   EXPECT_TRUE(decos1[0]->Is<ast::LocationDecoration>());
-  EXPECT_EQ(decos1[0]->As<ast::LocationDecoration>()->value(), 1u);
+  EXPECT_EQ(decos1[0]->As<ast::LocationDecoration>()->value, 1u);
 
-  ASSERT_EQ(e.value[1]->source().range.begin.line, 1u);
-  ASSERT_EQ(e.value[1]->source().range.begin.column, 58u);
-  ASSERT_EQ(e.value[1]->source().range.end.line, 1u);
-  ASSERT_EQ(e.value[1]->source().range.end.column, 62u);
+  ASSERT_EQ(e.value[1]->source.range.begin.line, 1u);
+  ASSERT_EQ(e.value[1]->source.range.begin.column, 58u);
+  ASSERT_EQ(e.value[1]->source.range.end.line, 1u);
+  ASSERT_EQ(e.value[1]->source.range.end.column, 62u);
 }
 
 }  // namespace
diff --git a/src/reader/wgsl/parser_impl_primary_expression_test.cc b/src/reader/wgsl/parser_impl_primary_expression_test.cc
index 28241a6..4a23abc 100644
--- a/src/reader/wgsl/parser_impl_primary_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_primary_expression_test.cc
@@ -29,7 +29,7 @@
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::IdentifierExpression>());
   auto* ident = e->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 }
 
 TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
@@ -43,31 +43,31 @@
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
   auto* ty = e->As<ast::TypeConstructorExpression>();
 
-  ASSERT_EQ(ty->values().size(), 4u);
-  const auto& val = ty->values();
+  ASSERT_EQ(ty->values.size(), 4u);
+  const auto& val = ty->values;
   ASSERT_TRUE(val[0]->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(val[0]->Is<ast::ScalarConstructorExpression>());
   auto* ident = val[0]->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(ident->literal()->Is<ast::SintLiteral>());
-  EXPECT_EQ(ident->literal()->As<ast::SintLiteral>()->value(), 1);
+  ASSERT_TRUE(ident->literal->Is<ast::SintLiteral>());
+  EXPECT_EQ(ident->literal->As<ast::SintLiteral>()->value, 1);
 
   ASSERT_TRUE(val[1]->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(val[1]->Is<ast::ScalarConstructorExpression>());
   ident = val[1]->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(ident->literal()->Is<ast::SintLiteral>());
-  EXPECT_EQ(ident->literal()->As<ast::SintLiteral>()->value(), 2);
+  ASSERT_TRUE(ident->literal->Is<ast::SintLiteral>());
+  EXPECT_EQ(ident->literal->As<ast::SintLiteral>()->value, 2);
 
   ASSERT_TRUE(val[2]->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(val[2]->Is<ast::ScalarConstructorExpression>());
   ident = val[2]->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(ident->literal()->Is<ast::SintLiteral>());
-  EXPECT_EQ(ident->literal()->As<ast::SintLiteral>()->value(), 3);
+  ASSERT_TRUE(ident->literal->Is<ast::SintLiteral>());
+  EXPECT_EQ(ident->literal->As<ast::SintLiteral>()->value, 3);
 
   ASSERT_TRUE(val[3]->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(val[3]->Is<ast::ScalarConstructorExpression>());
   ident = val[3]->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(ident->literal()->Is<ast::SintLiteral>());
-  EXPECT_EQ(ident->literal()->As<ast::SintLiteral>()->value(), 4);
+  ASSERT_TRUE(ident->literal->Is<ast::SintLiteral>());
+  EXPECT_EQ(ident->literal->As<ast::SintLiteral>()->value, 4);
 }
 
 TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_ZeroConstructor) {
@@ -81,7 +81,7 @@
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
   auto* ty = e->As<ast::TypeConstructorExpression>();
 
-  ASSERT_EQ(ty->values().size(), 0u);
+  ASSERT_EQ(ty->values.size(), 0u);
 }
 
 TEST_F(ParserImplTest, PrimaryExpression_TypeDecl_InvalidTypeDecl) {
@@ -141,11 +141,11 @@
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
 
   auto* constructor = e->As<ast::TypeConstructorExpression>();
-  ASSERT_TRUE(constructor->type()->Is<ast::TypeName>());
-  EXPECT_EQ(constructor->type()->As<ast::TypeName>()->name(),
+  ASSERT_TRUE(constructor->type->Is<ast::TypeName>());
+  EXPECT_EQ(constructor->type->As<ast::TypeName>()->name,
             p->builder().Symbols().Get("S"));
 
-  auto values = constructor->values();
+  auto values = constructor->values;
   ASSERT_EQ(values.size(), 0u);
 }
 
@@ -166,22 +166,22 @@
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
 
   auto* constructor = e->As<ast::TypeConstructorExpression>();
-  ASSERT_TRUE(constructor->type()->Is<ast::TypeName>());
-  EXPECT_EQ(constructor->type()->As<ast::TypeName>()->name(),
+  ASSERT_TRUE(constructor->type->Is<ast::TypeName>());
+  EXPECT_EQ(constructor->type->As<ast::TypeName>()->name,
             p->builder().Symbols().Get("S"));
 
-  auto values = constructor->values();
+  auto values = constructor->values;
   ASSERT_EQ(values.size(), 2u);
 
   ASSERT_TRUE(values[0]->Is<ast::ScalarConstructorExpression>());
   auto* val0 = values[0]->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(val0->literal()->Is<ast::UintLiteral>());
-  EXPECT_EQ(val0->literal()->As<ast::UintLiteral>()->value(), 1u);
+  ASSERT_TRUE(val0->literal->Is<ast::UintLiteral>());
+  EXPECT_EQ(val0->literal->As<ast::UintLiteral>()->value, 1u);
 
   ASSERT_TRUE(values[1]->Is<ast::ScalarConstructorExpression>());
   auto* val1 = values[1]->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(val1->literal()->Is<ast::FloatLiteral>());
-  EXPECT_EQ(val1->literal()->As<ast::FloatLiteral>()->value(), 2.f);
+  ASSERT_TRUE(val1->literal->Is<ast::FloatLiteral>());
+  EXPECT_EQ(val1->literal->As<ast::FloatLiteral>()->value, 2.f);
 }
 
 TEST_F(ParserImplTest, PrimaryExpression_ConstLiteral_True) {
@@ -194,8 +194,8 @@
   ASSERT_TRUE(e->Is<ast::ConstructorExpression>());
   ASSERT_TRUE(e->Is<ast::ScalarConstructorExpression>());
   auto* init = e->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  EXPECT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  EXPECT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, PrimaryExpression_ParenExpr) {
@@ -250,11 +250,11 @@
   ASSERT_TRUE(e->Is<ast::TypeConstructorExpression>());
 
   auto* c = e->As<ast::TypeConstructorExpression>();
-  ASSERT_TRUE(c->type()->Is<ast::F32>());
-  ASSERT_EQ(c->values().size(), 1u);
+  ASSERT_TRUE(c->type->Is<ast::F32>());
+  ASSERT_EQ(c->values.size(), 1u);
 
-  ASSERT_TRUE(c->values()[0]->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(c->values()[0]->Is<ast::ScalarConstructorExpression>());
+  ASSERT_TRUE(c->values[0]->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(c->values[0]->Is<ast::ScalarConstructorExpression>());
 }
 
 TEST_F(ParserImplTest, PrimaryExpression_Bitcast) {
@@ -268,9 +268,9 @@
   ASSERT_TRUE(e->Is<ast::BitcastExpression>());
 
   auto* c = e->As<ast::BitcastExpression>();
-  ASSERT_TRUE(c->type()->Is<ast::F32>());
-  ASSERT_TRUE(c->expr()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(c->expr()->Is<ast::ScalarConstructorExpression>());
+  ASSERT_TRUE(c->type->Is<ast::F32>());
+  ASSERT_TRUE(c->expr->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(c->expr->Is<ast::ScalarConstructorExpression>());
 }
 
 TEST_F(ParserImplTest, PrimaryExpression_Bitcast_MissingGreaterThan) {
diff --git a/src/reader/wgsl/parser_impl_relational_expression_test.cc b/src/reader/wgsl/parser_impl_relational_expression_test.cc
index 8058487..2bbfcbf 100644
--- a/src/reader/wgsl/parser_impl_relational_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_relational_expression_test.cc
@@ -29,17 +29,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kLessThan, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kLessThan, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Register("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThan) {
@@ -52,17 +52,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kGreaterThan, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kGreaterThan, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Register("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, RelationalExpression_Parses_LessThanEqual) {
@@ -75,17 +75,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kLessThanEqual, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kLessThanEqual, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Register("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, RelationalExpression_Parses_GreaterThanEqual) {
@@ -98,17 +98,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kGreaterThanEqual, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kGreaterThanEqual, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Register("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, RelationalExpression_InvalidLHS) {
diff --git a/src/reader/wgsl/parser_impl_sampler_type_test.cc b/src/reader/wgsl/parser_impl_sampler_type_test.cc
index a7891e2..32de50d 100644
--- a/src/reader/wgsl/parser_impl_sampler_type_test.cc
+++ b/src/reader/wgsl/parser_impl_sampler_type_test.cc
@@ -37,7 +37,7 @@
   ASSERT_TRUE(t->Is<ast::Sampler>());
   EXPECT_FALSE(t->As<ast::Sampler>()->IsComparison());
   EXPECT_FALSE(p->has_error());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 8u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 8u}}));
 }
 
 TEST_F(ParserImplTest, SamplerType_ComparisonSampler) {
@@ -49,7 +49,7 @@
   ASSERT_TRUE(t->Is<ast::Sampler>());
   EXPECT_TRUE(t->As<ast::Sampler>()->IsComparison());
   EXPECT_FALSE(p->has_error());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 19u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 19u}}));
 }
 
 }  // namespace
diff --git a/src/reader/wgsl/parser_impl_shift_expression_test.cc b/src/reader/wgsl/parser_impl_shift_expression_test.cc
index e4d93e9..58675d6 100644
--- a/src/reader/wgsl/parser_impl_shift_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_shift_expression_test.cc
@@ -29,17 +29,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kShiftLeft, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kShiftLeft, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, ShiftExpression_Parses_ShiftRight) {
@@ -52,17 +52,17 @@
 
   ASSERT_TRUE(e->Is<ast::BinaryExpression>());
   auto* rel = e->As<ast::BinaryExpression>();
-  EXPECT_EQ(ast::BinaryOp::kShiftRight, rel->op());
+  EXPECT_EQ(ast::BinaryOp::kShiftRight, rel->op);
 
-  ASSERT_TRUE(rel->lhs()->Is<ast::IdentifierExpression>());
-  auto* ident = rel->lhs()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
+  auto* ident = rel->lhs->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(rel->rhs()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(rel->rhs()->Is<ast::ScalarConstructorExpression>());
-  auto* init = rel->rhs()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::BoolLiteral>());
-  ASSERT_TRUE(init->literal()->As<ast::BoolLiteral>()->IsTrue());
+  ASSERT_TRUE(rel->rhs->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(rel->rhs->Is<ast::ScalarConstructorExpression>());
+  auto* init = rel->rhs->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::BoolLiteral>());
+  ASSERT_TRUE(init->literal->As<ast::BoolLiteral>()->value);
 }
 
 TEST_F(ParserImplTest, ShiftExpression_InvalidSpaceLeft) {
diff --git a/src/reader/wgsl/parser_impl_singular_expression_test.cc b/src/reader/wgsl/parser_impl_singular_expression_test.cc
index 36b803d..50afbb0 100644
--- a/src/reader/wgsl/parser_impl_singular_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_singular_expression_test.cc
@@ -30,15 +30,15 @@
   ASSERT_TRUE(e->Is<ast::ArrayAccessorExpression>());
   auto* ary = e->As<ast::ArrayAccessorExpression>();
 
-  ASSERT_TRUE(ary->array()->Is<ast::IdentifierExpression>());
-  auto* ident = ary->array()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(ary->array->Is<ast::IdentifierExpression>());
+  auto* ident = ary->array->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(ary->idx_expr()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(ary->idx_expr()->Is<ast::ScalarConstructorExpression>());
-  auto* c = ary->idx_expr()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(c->literal()->Is<ast::SintLiteral>());
-  EXPECT_EQ(c->literal()->As<ast::SintLiteral>()->value(), 1);
+  ASSERT_TRUE(ary->index->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(ary->index->Is<ast::ScalarConstructorExpression>());
+  auto* c = ary->index->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(c->literal->Is<ast::SintLiteral>());
+  EXPECT_EQ(c->literal->As<ast::SintLiteral>()->value, 1);
 }
 
 TEST_F(ParserImplTest, SingularExpression_Array_ExpressionIndex) {
@@ -52,11 +52,11 @@
   ASSERT_TRUE(e->Is<ast::ArrayAccessorExpression>());
   auto* ary = e->As<ast::ArrayAccessorExpression>();
 
-  ASSERT_TRUE(ary->array()->Is<ast::IdentifierExpression>());
-  auto* ident = ary->array()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(ary->array->Is<ast::IdentifierExpression>());
+  auto* ident = ary->array->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(ary->idx_expr()->Is<ast::BinaryExpression>());
+  ASSERT_TRUE(ary->index->Is<ast::BinaryExpression>());
 }
 
 TEST_F(ParserImplTest, SingularExpression_Array_MissingIndex) {
@@ -100,9 +100,9 @@
   ASSERT_TRUE(e->Is<ast::CallExpression>());
   auto* c = e->As<ast::CallExpression>();
 
-  EXPECT_EQ(c->func()->symbol(), p->builder().Symbols().Get("a"));
+  EXPECT_EQ(c->func->symbol, p->builder().Symbols().Get("a"));
 
-  EXPECT_EQ(c->args().size(), 0u);
+  EXPECT_EQ(c->args.size(), 0u);
 }
 
 TEST_F(ParserImplTest, SingularExpression_Call_WithArgs) {
@@ -116,12 +116,12 @@
   ASSERT_TRUE(e->Is<ast::CallExpression>());
   auto* c = e->As<ast::CallExpression>();
 
-  EXPECT_EQ(c->func()->symbol(), p->builder().Symbols().Get("test"));
+  EXPECT_EQ(c->func->symbol, p->builder().Symbols().Get("test"));
 
-  EXPECT_EQ(c->args().size(), 3u);
-  EXPECT_TRUE(c->args()[0]->Is<ast::ConstructorExpression>());
-  EXPECT_TRUE(c->args()[1]->Is<ast::IdentifierExpression>());
-  EXPECT_TRUE(c->args()[2]->Is<ast::BinaryExpression>());
+  EXPECT_EQ(c->args.size(), 3u);
+  EXPECT_TRUE(c->args[0]->Is<ast::ConstructorExpression>());
+  EXPECT_TRUE(c->args[1]->Is<ast::IdentifierExpression>());
+  EXPECT_TRUE(c->args[2]->Is<ast::BinaryExpression>());
 }
 
 TEST_F(ParserImplTest, SingularExpression_Call_TrailingComma) {
@@ -133,7 +133,7 @@
 
   ASSERT_TRUE(e->Is<ast::CallExpression>());
   auto* c = e->As<ast::CallExpression>();
-  EXPECT_EQ(c->args().size(), 1u);
+  EXPECT_EQ(c->args.size(), 1u);
 }
 
 TEST_F(ParserImplTest, SingularExpression_Call_InvalidArg) {
@@ -166,12 +166,12 @@
   ASSERT_TRUE(e->Is<ast::MemberAccessorExpression>());
 
   auto* m = e->As<ast::MemberAccessorExpression>();
-  ASSERT_TRUE(m->structure()->Is<ast::IdentifierExpression>());
-  EXPECT_EQ(m->structure()->As<ast::IdentifierExpression>()->symbol(),
+  ASSERT_TRUE(m->structure->Is<ast::IdentifierExpression>());
+  EXPECT_EQ(m->structure->As<ast::IdentifierExpression>()->symbol,
             p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(m->member()->Is<ast::IdentifierExpression>());
-  EXPECT_EQ(m->member()->As<ast::IdentifierExpression>()->symbol(),
+  ASSERT_TRUE(m->member->Is<ast::IdentifierExpression>());
+  EXPECT_EQ(m->member->As<ast::IdentifierExpression>()->symbol,
             p->builder().Symbols().Get("b"));
 }
 
@@ -217,23 +217,23 @@
   ASSERT_TRUE(outer_accessor);
 
   const auto* outer_array =
-      outer_accessor->array()->As<ast::IdentifierExpression>();
+      outer_accessor->array->As<ast::IdentifierExpression>();
   ASSERT_TRUE(outer_array);
-  EXPECT_EQ(outer_array->symbol(), p->builder().Symbols().Get("a"));
+  EXPECT_EQ(outer_array->symbol, p->builder().Symbols().Get("a"));
 
   const auto* inner_accessor =
-      outer_accessor->idx_expr()->As<ast::ArrayAccessorExpression>();
+      outer_accessor->index->As<ast::ArrayAccessorExpression>();
   ASSERT_TRUE(inner_accessor);
 
   const auto* inner_array =
-      inner_accessor->array()->As<ast::IdentifierExpression>();
+      inner_accessor->array->As<ast::IdentifierExpression>();
   ASSERT_TRUE(inner_array);
-  EXPECT_EQ(inner_array->symbol(), p->builder().Symbols().Get("b"));
+  EXPECT_EQ(inner_array->symbol, p->builder().Symbols().Get("b"));
 
   const auto* index_expr =
-      inner_accessor->idx_expr()->As<ast::IdentifierExpression>();
+      inner_accessor->index->As<ast::IdentifierExpression>();
   ASSERT_TRUE(index_expr);
-  EXPECT_EQ(index_expr->symbol(), p->builder().Symbols().Get("c"));
+  EXPECT_EQ(index_expr->symbol, p->builder().Symbols().Get("c"));
 }
 
 TEST_F(ParserImplTest, SingularExpression_PostfixPlusPlus) {
diff --git a/src/reader/wgsl/parser_impl_statement_test.cc b/src/reader/wgsl/parser_impl_statement_test.cc
index 153ebd3..5a63a03 100644
--- a/src/reader/wgsl/parser_impl_statement_test.cc
+++ b/src/reader/wgsl/parser_impl_statement_test.cc
@@ -45,7 +45,7 @@
   EXPECT_FALSE(e.errored);
   ASSERT_TRUE(e->Is<ast::ReturnStatement>());
   auto* ret = e->As<ast::ReturnStatement>();
-  ASSERT_EQ(ret->value(), nullptr);
+  ASSERT_EQ(ret->value, nullptr);
 }
 
 TEST_F(ParserImplTest, Statement_Return_Value) {
@@ -57,8 +57,8 @@
   EXPECT_FALSE(e.errored);
   ASSERT_TRUE(e->Is<ast::ReturnStatement>());
   auto* ret = e->As<ast::ReturnStatement>();
-  ASSERT_NE(ret->value(), nullptr);
-  EXPECT_TRUE(ret->value()->Is<ast::BinaryExpression>());
+  ASSERT_NE(ret->value, nullptr);
+  EXPECT_TRUE(ret->value->Is<ast::BinaryExpression>());
 }
 
 TEST_F(ParserImplTest, Statement_Return_MissingSemi) {
@@ -261,8 +261,9 @@
   EXPECT_TRUE(e.matched);
   EXPECT_FALSE(e.errored);
   ASSERT_TRUE(e->Is<ast::BlockStatement>());
-  EXPECT_TRUE(
-      e->As<ast::BlockStatement>()->get(0)->Is<ast::VariableDeclStatement>());
+  EXPECT_TRUE(e->As<ast::BlockStatement>()
+                  ->statements[0]
+                  ->Is<ast::VariableDeclStatement>());
 }
 
 TEST_F(ParserImplTest, Statement_Body_Invalid) {
diff --git a/src/reader/wgsl/parser_impl_struct_body_decl_test.cc b/src/reader/wgsl/parser_impl_struct_body_decl_test.cc
index cd0b526..729fac4 100644
--- a/src/reader/wgsl/parser_impl_struct_body_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_body_decl_test.cc
@@ -30,9 +30,9 @@
   ASSERT_EQ(m.value.size(), 1u);
 
   const auto* mem = m.value[0];
-  EXPECT_EQ(mem->symbol(), builder.Symbols().Get("a"));
-  EXPECT_TRUE(mem->type()->Is<ast::I32>());
-  EXPECT_EQ(mem->decorations().size(), 0u);
+  EXPECT_EQ(mem->symbol, builder.Symbols().Get("a"));
+  EXPECT_TRUE(mem->type->Is<ast::I32>());
+  EXPECT_EQ(mem->decorations.size(), 0u);
 }
 
 TEST_F(ParserImplTest, StructBodyDecl_ParsesEmpty) {
diff --git a/src/reader/wgsl/parser_impl_struct_decl_test.cc b/src/reader/wgsl/parser_impl_struct_decl_test.cc
index 1d5b783..e7c4e9f 100644
--- a/src/reader/wgsl/parser_impl_struct_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_decl_test.cc
@@ -36,10 +36,10 @@
   EXPECT_FALSE(s.errored);
   EXPECT_TRUE(s.matched);
   ASSERT_NE(s.value, nullptr);
-  ASSERT_EQ(s->name(), p->builder().Symbols().Register("S"));
-  ASSERT_EQ(s->members().size(), 2u);
-  EXPECT_EQ(s->members()[0]->symbol(), p->builder().Symbols().Register("a"));
-  EXPECT_EQ(s->members()[1]->symbol(), p->builder().Symbols().Register("b"));
+  ASSERT_EQ(s->name, p->builder().Symbols().Register("S"));
+  ASSERT_EQ(s->members.size(), 2u);
+  EXPECT_EQ(s->members[0]->symbol, p->builder().Symbols().Register("a"));
+  EXPECT_EQ(s->members[1]->symbol, p->builder().Symbols().Register("b"));
 }
 
 TEST_F(ParserImplTest, StructDecl_ParsesWithDecoration) {
@@ -58,12 +58,12 @@
   EXPECT_FALSE(s.errored);
   EXPECT_TRUE(s.matched);
   ASSERT_NE(s.value, nullptr);
-  ASSERT_EQ(s->name(), p->builder().Symbols().Register("B"));
-  ASSERT_EQ(s->members().size(), 2u);
-  EXPECT_EQ(s->members()[0]->symbol(), p->builder().Symbols().Register("a"));
-  EXPECT_EQ(s->members()[1]->symbol(), p->builder().Symbols().Register("b"));
-  ASSERT_EQ(s->decorations().size(), 1u);
-  EXPECT_TRUE(s->decorations()[0]->Is<ast::StructBlockDecoration>());
+  ASSERT_EQ(s->name, p->builder().Symbols().Register("B"));
+  ASSERT_EQ(s->members.size(), 2u);
+  EXPECT_EQ(s->members[0]->symbol, p->builder().Symbols().Register("a"));
+  EXPECT_EQ(s->members[1]->symbol, p->builder().Symbols().Register("b"));
+  ASSERT_EQ(s->decorations.size(), 1u);
+  EXPECT_TRUE(s->decorations[0]->Is<ast::StructBlockDecoration>());
 }
 
 TEST_F(ParserImplTest, StructDecl_ParsesWithMultipleDecoration) {
@@ -83,13 +83,13 @@
   EXPECT_FALSE(s.errored);
   EXPECT_TRUE(s.matched);
   ASSERT_NE(s.value, nullptr);
-  ASSERT_EQ(s->name(), p->builder().Symbols().Register("S"));
-  ASSERT_EQ(s->members().size(), 2u);
-  EXPECT_EQ(s->members()[0]->symbol(), p->builder().Symbols().Register("a"));
-  EXPECT_EQ(s->members()[1]->symbol(), p->builder().Symbols().Register("b"));
-  ASSERT_EQ(s->decorations().size(), 2u);
-  EXPECT_TRUE(s->decorations()[0]->Is<ast::StructBlockDecoration>());
-  EXPECT_TRUE(s->decorations()[1]->Is<ast::StructBlockDecoration>());
+  ASSERT_EQ(s->name, p->builder().Symbols().Register("S"));
+  ASSERT_EQ(s->members.size(), 2u);
+  EXPECT_EQ(s->members[0]->symbol, p->builder().Symbols().Register("a"));
+  EXPECT_EQ(s->members[1]->symbol, p->builder().Symbols().Register("b"));
+  ASSERT_EQ(s->decorations.size(), 2u);
+  EXPECT_TRUE(s->decorations[0]->Is<ast::StructBlockDecoration>());
+  EXPECT_TRUE(s->decorations[1]->Is<ast::StructBlockDecoration>());
 }
 
 TEST_F(ParserImplTest, StructDecl_EmptyMembers) {
@@ -104,7 +104,7 @@
   EXPECT_FALSE(s.errored);
   EXPECT_TRUE(s.matched);
   ASSERT_NE(s.value, nullptr);
-  ASSERT_EQ(s->members().size(), 0u);
+  ASSERT_EQ(s->members.size(), 0u);
 }
 
 TEST_F(ParserImplTest, StructDecl_MissingIdent) {
diff --git a/src/reader/wgsl/parser_impl_struct_member_decoration_test.cc b/src/reader/wgsl/parser_impl_struct_member_decoration_test.cc
index 6add8ee..eee2718 100644
--- a/src/reader/wgsl/parser_impl_struct_member_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_member_decoration_test.cc
@@ -32,7 +32,7 @@
   ASSERT_TRUE(member_deco->Is<ast::StructMemberSizeDecoration>());
 
   auto* o = member_deco->As<ast::StructMemberSizeDecoration>();
-  EXPECT_EQ(o->size(), 4u);
+  EXPECT_EQ(o->size, 4u);
 }
 
 TEST_F(ParserImplTest, Decoration_Size_MissingLeftParen) {
@@ -90,7 +90,7 @@
   ASSERT_TRUE(member_deco->Is<ast::StructMemberAlignDecoration>());
 
   auto* o = member_deco->As<ast::StructMemberAlignDecoration>();
-  EXPECT_EQ(o->align(), 4u);
+  EXPECT_EQ(o->align, 4u);
 }
 
 TEST_F(ParserImplTest, Decoration_Align_MissingLeftParen) {
diff --git a/src/reader/wgsl/parser_impl_struct_member_test.cc b/src/reader/wgsl/parser_impl_struct_member_test.cc
index 2ba2260..8a514ac 100644
--- a/src/reader/wgsl/parser_impl_struct_member_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_member_test.cc
@@ -34,12 +34,12 @@
   ASSERT_FALSE(m.errored);
   ASSERT_NE(m.value, nullptr);
 
-  EXPECT_EQ(m->symbol(), builder.Symbols().Get("a"));
-  EXPECT_TRUE(m->type()->Is<ast::I32>());
-  EXPECT_EQ(m->decorations().size(), 0u);
+  EXPECT_EQ(m->symbol, builder.Symbols().Get("a"));
+  EXPECT_TRUE(m->type->Is<ast::I32>());
+  EXPECT_EQ(m->decorations.size(), 0u);
 
-  EXPECT_EQ(m->source().range, (Source::Range{{1u, 1u}, {1u, 2u}}));
-  EXPECT_EQ(m->type()->source().range, (Source::Range{{1u, 5u}, {1u, 8u}}));
+  EXPECT_EQ(m->source.range, (Source::Range{{1u, 1u}, {1u, 2u}}));
+  EXPECT_EQ(m->type->source.range, (Source::Range{{1u, 5u}, {1u, 8u}}));
 }
 
 TEST_F(ParserImplTest, StructMember_ParsesWithAlignDecoration) {
@@ -57,15 +57,15 @@
   ASSERT_FALSE(m.errored);
   ASSERT_NE(m.value, nullptr);
 
-  EXPECT_EQ(m->symbol(), builder.Symbols().Get("a"));
-  EXPECT_TRUE(m->type()->Is<ast::I32>());
-  EXPECT_EQ(m->decorations().size(), 1u);
-  EXPECT_TRUE(m->decorations()[0]->Is<ast::StructMemberAlignDecoration>());
-  EXPECT_EQ(
-      m->decorations()[0]->As<ast::StructMemberAlignDecoration>()->align(), 2u);
+  EXPECT_EQ(m->symbol, builder.Symbols().Get("a"));
+  EXPECT_TRUE(m->type->Is<ast::I32>());
+  EXPECT_EQ(m->decorations.size(), 1u);
+  EXPECT_TRUE(m->decorations[0]->Is<ast::StructMemberAlignDecoration>());
+  EXPECT_EQ(m->decorations[0]->As<ast::StructMemberAlignDecoration>()->align,
+            2u);
 
-  EXPECT_EQ(m->source().range, (Source::Range{{1u, 14u}, {1u, 15u}}));
-  EXPECT_EQ(m->type()->source().range, (Source::Range{{1u, 18u}, {1u, 21u}}));
+  EXPECT_EQ(m->source.range, (Source::Range{{1u, 14u}, {1u, 15u}}));
+  EXPECT_EQ(m->type->source.range, (Source::Range{{1u, 18u}, {1u, 21u}}));
 }
 
 TEST_F(ParserImplTest, StructMember_ParsesWithSizeDecoration) {
@@ -83,15 +83,14 @@
   ASSERT_FALSE(m.errored);
   ASSERT_NE(m.value, nullptr);
 
-  EXPECT_EQ(m->symbol(), builder.Symbols().Get("a"));
-  EXPECT_TRUE(m->type()->Is<ast::I32>());
-  EXPECT_EQ(m->decorations().size(), 1u);
-  EXPECT_TRUE(m->decorations()[0]->Is<ast::StructMemberSizeDecoration>());
-  EXPECT_EQ(m->decorations()[0]->As<ast::StructMemberSizeDecoration>()->size(),
-            2u);
+  EXPECT_EQ(m->symbol, builder.Symbols().Get("a"));
+  EXPECT_TRUE(m->type->Is<ast::I32>());
+  EXPECT_EQ(m->decorations.size(), 1u);
+  EXPECT_TRUE(m->decorations[0]->Is<ast::StructMemberSizeDecoration>());
+  EXPECT_EQ(m->decorations[0]->As<ast::StructMemberSizeDecoration>()->size, 2u);
 
-  EXPECT_EQ(m->source().range, (Source::Range{{1u, 13u}, {1u, 14u}}));
-  EXPECT_EQ(m->type()->source().range, (Source::Range{{1u, 17u}, {1u, 20u}}));
+  EXPECT_EQ(m->source.range, (Source::Range{{1u, 13u}, {1u, 14u}}));
+  EXPECT_EQ(m->type->source.range, (Source::Range{{1u, 17u}, {1u, 20u}}));
 }
 
 TEST_F(ParserImplTest, StructMember_ParsesWithDecoration) {
@@ -109,15 +108,14 @@
   ASSERT_FALSE(m.errored);
   ASSERT_NE(m.value, nullptr);
 
-  EXPECT_EQ(m->symbol(), builder.Symbols().Get("a"));
-  EXPECT_TRUE(m->type()->Is<ast::I32>());
-  EXPECT_EQ(m->decorations().size(), 1u);
-  EXPECT_TRUE(m->decorations()[0]->Is<ast::StructMemberSizeDecoration>());
-  EXPECT_EQ(m->decorations()[0]->As<ast::StructMemberSizeDecoration>()->size(),
-            2u);
+  EXPECT_EQ(m->symbol, builder.Symbols().Get("a"));
+  EXPECT_TRUE(m->type->Is<ast::I32>());
+  EXPECT_EQ(m->decorations.size(), 1u);
+  EXPECT_TRUE(m->decorations[0]->Is<ast::StructMemberSizeDecoration>());
+  EXPECT_EQ(m->decorations[0]->As<ast::StructMemberSizeDecoration>()->size, 2u);
 
-  EXPECT_EQ(m->source().range, (Source::Range{{1u, 13u}, {1u, 14u}}));
-  EXPECT_EQ(m->type()->source().range, (Source::Range{{1u, 17u}, {1u, 20u}}));
+  EXPECT_EQ(m->source.range, (Source::Range{{1u, 13u}, {1u, 14u}}));
+  EXPECT_EQ(m->type->source.range, (Source::Range{{1u, 17u}, {1u, 20u}}));
 }
 
 TEST_F(ParserImplTest, StructMember_ParsesWithMultipleDecorations) {
@@ -136,18 +134,17 @@
   ASSERT_FALSE(m.errored);
   ASSERT_NE(m.value, nullptr);
 
-  EXPECT_EQ(m->symbol(), builder.Symbols().Get("a"));
-  EXPECT_TRUE(m->type()->Is<ast::I32>());
-  EXPECT_EQ(m->decorations().size(), 2u);
-  EXPECT_TRUE(m->decorations()[0]->Is<ast::StructMemberSizeDecoration>());
-  EXPECT_EQ(m->decorations()[0]->As<ast::StructMemberSizeDecoration>()->size(),
-            2u);
-  EXPECT_TRUE(m->decorations()[1]->Is<ast::StructMemberAlignDecoration>());
-  EXPECT_EQ(
-      m->decorations()[1]->As<ast::StructMemberAlignDecoration>()->align(), 4u);
+  EXPECT_EQ(m->symbol, builder.Symbols().Get("a"));
+  EXPECT_TRUE(m->type->Is<ast::I32>());
+  EXPECT_EQ(m->decorations.size(), 2u);
+  EXPECT_TRUE(m->decorations[0]->Is<ast::StructMemberSizeDecoration>());
+  EXPECT_EQ(m->decorations[0]->As<ast::StructMemberSizeDecoration>()->size, 2u);
+  EXPECT_TRUE(m->decorations[1]->Is<ast::StructMemberAlignDecoration>());
+  EXPECT_EQ(m->decorations[1]->As<ast::StructMemberAlignDecoration>()->align,
+            4u);
 
-  EXPECT_EQ(m->source().range, (Source::Range{{2u, 14u}, {2u, 15u}}));
-  EXPECT_EQ(m->type()->source().range, (Source::Range{{2u, 18u}, {2u, 21u}}));
+  EXPECT_EQ(m->source.range, (Source::Range{{2u, 14u}, {2u, 15u}}));
+  EXPECT_EQ(m->type->source.range, (Source::Range{{2u, 18u}, {2u, 21u}}));
 }
 
 TEST_F(ParserImplTest, StructMember_InvalidDecoration) {
diff --git a/src/reader/wgsl/parser_impl_switch_body_test.cc b/src/reader/wgsl/parser_impl_switch_body_test.cc
index e9b7809..f6fa138 100644
--- a/src/reader/wgsl/parser_impl_switch_body_test.cc
+++ b/src/reader/wgsl/parser_impl_switch_body_test.cc
@@ -29,10 +29,10 @@
   ASSERT_TRUE(e->Is<ast::CaseStatement>());
   EXPECT_FALSE(e->IsDefault());
   auto* stmt = e->As<ast::CaseStatement>();
-  ASSERT_EQ(stmt->selectors().size(), 1u);
-  EXPECT_EQ(stmt->selectors()[0]->value_as_u32(), 1u);
-  ASSERT_EQ(e->body()->size(), 1u);
-  EXPECT_TRUE(e->body()->get(0)->Is<ast::AssignmentStatement>());
+  ASSERT_EQ(stmt->selectors.size(), 1u);
+  EXPECT_EQ(stmt->selectors[0]->ValueAsU32(), 1u);
+  ASSERT_EQ(e->body->statements.size(), 1u);
+  EXPECT_TRUE(e->body->statements[0]->Is<ast::AssignmentStatement>());
 }
 
 TEST_F(ParserImplTest, SwitchBody_Case_TrailingComma) {
@@ -45,9 +45,9 @@
   ASSERT_TRUE(e->Is<ast::CaseStatement>());
   EXPECT_FALSE(e->IsDefault());
   auto* stmt = e->As<ast::CaseStatement>();
-  ASSERT_EQ(stmt->selectors().size(), 2u);
-  EXPECT_EQ(stmt->selectors()[0]->value_as_u32(), 1u);
-  EXPECT_EQ(stmt->selectors()[1]->value_as_u32(), 2u);
+  ASSERT_EQ(stmt->selectors.size(), 2u);
+  EXPECT_EQ(stmt->selectors[0]->ValueAsU32(), 1u);
+  EXPECT_EQ(stmt->selectors[1]->ValueAsU32(), 2u);
 }
 
 TEST_F(ParserImplTest, SwitchBody_Case_InvalidConstLiteral) {
@@ -129,10 +129,10 @@
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::CaseStatement>());
   EXPECT_FALSE(e->IsDefault());
-  ASSERT_EQ(e->body()->size(), 0u);
-  ASSERT_EQ(e->selectors().size(), 2u);
-  ASSERT_EQ(e->selectors()[0]->value_as_i32(), 1);
-  ASSERT_EQ(e->selectors()[1]->value_as_i32(), 2);
+  ASSERT_EQ(e->body->statements.size(), 0u);
+  ASSERT_EQ(e->selectors.size(), 2u);
+  ASSERT_EQ(e->selectors[0]->ValueAsI32(), 1);
+  ASSERT_EQ(e->selectors[1]->ValueAsI32(), 2);
 }
 
 TEST_F(ParserImplTest, SwitchBody_Case_MultipleSelectorsMissingColon) {
@@ -174,8 +174,8 @@
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::CaseStatement>());
   EXPECT_TRUE(e->IsDefault());
-  ASSERT_EQ(e->body()->size(), 1u);
-  EXPECT_TRUE(e->body()->get(0)->Is<ast::AssignmentStatement>());
+  ASSERT_EQ(e->body->statements.size(), 1u);
+  EXPECT_TRUE(e->body->statements[0]->Is<ast::AssignmentStatement>());
 }
 
 TEST_F(ParserImplTest, SwitchBody_Default_MissingColon) {
diff --git a/src/reader/wgsl/parser_impl_switch_stmt_test.cc b/src/reader/wgsl/parser_impl_switch_stmt_test.cc
index 5d73e04..4963356 100644
--- a/src/reader/wgsl/parser_impl_switch_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_switch_stmt_test.cc
@@ -30,9 +30,9 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::SwitchStatement>());
-  ASSERT_EQ(e->body().size(), 2u);
-  EXPECT_FALSE(e->body()[0]->IsDefault());
-  EXPECT_FALSE(e->body()[1]->IsDefault());
+  ASSERT_EQ(e->body.size(), 2u);
+  EXPECT_FALSE(e->body[0]->IsDefault());
+  EXPECT_FALSE(e->body[1]->IsDefault());
 }
 
 TEST_F(ParserImplTest, SwitchStmt_Empty) {
@@ -43,7 +43,7 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::SwitchStatement>());
-  ASSERT_EQ(e->body().size(), 0u);
+  ASSERT_EQ(e->body.size(), 0u);
 }
 
 TEST_F(ParserImplTest, SwitchStmt_DefaultInMiddle) {
@@ -59,10 +59,10 @@
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::SwitchStatement>());
 
-  ASSERT_EQ(e->body().size(), 3u);
-  ASSERT_FALSE(e->body()[0]->IsDefault());
-  ASSERT_TRUE(e->body()[1]->IsDefault());
-  ASSERT_FALSE(e->body()[2]->IsDefault());
+  ASSERT_EQ(e->body.size(), 3u);
+  ASSERT_FALSE(e->body[0]->IsDefault());
+  ASSERT_TRUE(e->body[1]->IsDefault());
+  ASSERT_FALSE(e->body[2]->IsDefault());
 }
 
 TEST_F(ParserImplTest, SwitchStmt_InvalidExpression) {
diff --git a/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc b/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc
index c006882..970e430 100644
--- a/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc
+++ b/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc
@@ -40,7 +40,7 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::Sampler>());
   ASSERT_FALSE(t->As<ast::Sampler>()->IsComparison());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 8u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 8u}}));
 }
 
 TEST_F(ParserImplTest, TextureSamplerTypes_SamplerComparison) {
@@ -52,7 +52,7 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::Sampler>());
   ASSERT_TRUE(t->As<ast::Sampler>()->IsComparison());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 19u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 19u}}));
 }
 
 TEST_F(ParserImplTest, TextureSamplerTypes_DepthTexture) {
@@ -64,8 +64,8 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::Texture>());
   ASSERT_TRUE(t->Is<ast::DepthTexture>());
-  EXPECT_EQ(t->As<ast::Texture>()->dim(), ast::TextureDimension::k2d);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 17u}}));
+  EXPECT_EQ(t->As<ast::Texture>()->dim, ast::TextureDimension::k2d);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 17u}}));
 }
 
 TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_F32) {
@@ -77,9 +77,9 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::Texture>());
   ASSERT_TRUE(t->Is<ast::SampledTexture>());
-  ASSERT_TRUE(t->As<ast::SampledTexture>()->type()->Is<ast::F32>());
-  EXPECT_EQ(t->As<ast::Texture>()->dim(), ast::TextureDimension::k1d);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 16u}}));
+  ASSERT_TRUE(t->As<ast::SampledTexture>()->type->Is<ast::F32>());
+  EXPECT_EQ(t->As<ast::Texture>()->dim, ast::TextureDimension::k1d);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 16u}}));
 }
 
 TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_I32) {
@@ -91,9 +91,9 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::Texture>());
   ASSERT_TRUE(t->Is<ast::SampledTexture>());
-  ASSERT_TRUE(t->As<ast::SampledTexture>()->type()->Is<ast::I32>());
-  EXPECT_EQ(t->As<ast::Texture>()->dim(), ast::TextureDimension::k2d);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 16u}}));
+  ASSERT_TRUE(t->As<ast::SampledTexture>()->type->Is<ast::I32>());
+  EXPECT_EQ(t->As<ast::Texture>()->dim, ast::TextureDimension::k2d);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 16u}}));
 }
 
 TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_U32) {
@@ -105,9 +105,9 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::Texture>());
   ASSERT_TRUE(t->Is<ast::SampledTexture>());
-  ASSERT_TRUE(t->As<ast::SampledTexture>()->type()->Is<ast::U32>());
-  EXPECT_EQ(t->As<ast::Texture>()->dim(), ast::TextureDimension::k3d);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 16u}}));
+  ASSERT_TRUE(t->As<ast::SampledTexture>()->type->Is<ast::U32>());
+  EXPECT_EQ(t->As<ast::Texture>()->dim, ast::TextureDimension::k3d);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 16u}}));
 }
 
 TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_Invalid) {
@@ -159,9 +159,9 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::Texture>());
   ASSERT_TRUE(t->Is<ast::MultisampledTexture>());
-  ASSERT_TRUE(t->As<ast::MultisampledTexture>()->type()->Is<ast::I32>());
-  EXPECT_EQ(t->As<ast::Texture>()->dim(), ast::TextureDimension::k2d);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 29u}}));
+  ASSERT_TRUE(t->As<ast::MultisampledTexture>()->type->Is<ast::I32>());
+  EXPECT_EQ(t->As<ast::Texture>()->dim, ast::TextureDimension::k2d);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 29u}}));
 }
 
 TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_Invalid) {
@@ -214,11 +214,10 @@
 
   ASSERT_TRUE(t->Is<ast::Texture>());
   ASSERT_TRUE(t->Is<ast::StorageTexture>());
-  EXPECT_EQ(t->As<ast::StorageTexture>()->image_format(),
-            ast::ImageFormat::kR8Unorm);
-  EXPECT_EQ(t->As<ast::StorageTexture>()->access(), ast::Access::kRead);
-  EXPECT_EQ(t->As<ast::Texture>()->dim(), ast::TextureDimension::k1d);
-  EXPECT_EQ(t->source().range, (Source::Range{{1u, 1u}, {1u, 34u}}));
+  EXPECT_EQ(t->As<ast::StorageTexture>()->format, ast::ImageFormat::kR8Unorm);
+  EXPECT_EQ(t->As<ast::StorageTexture>()->access, ast::Access::kRead);
+  EXPECT_EQ(t->As<ast::Texture>()->dim, ast::TextureDimension::k1d);
+  EXPECT_EQ(t->source.range, (Source::Range{{1u, 1u}, {1u, 34u}}));
 }
 
 TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Writeonly2dR16Float) {
@@ -231,11 +230,10 @@
 
   ASSERT_TRUE(t->Is<ast::Texture>());
   ASSERT_TRUE(t->Is<ast::StorageTexture>());
-  EXPECT_EQ(t->As<ast::StorageTexture>()->image_format(),
-            ast::ImageFormat::kR16Float);
-  EXPECT_EQ(t->As<ast::StorageTexture>()->access(), ast::Access::kWrite);
-  EXPECT_EQ(t->As<ast::Texture>()->dim(), ast::TextureDimension::k2d);
-  EXPECT_EQ(t->source().range, (Source::Range{{1u, 1u}, {1u, 36u}}));
+  EXPECT_EQ(t->As<ast::StorageTexture>()->format, ast::ImageFormat::kR16Float);
+  EXPECT_EQ(t->As<ast::StorageTexture>()->access, ast::Access::kWrite);
+  EXPECT_EQ(t->As<ast::Texture>()->dim, ast::TextureDimension::k2d);
+  EXPECT_EQ(t->source.range, (Source::Range{{1u, 1u}, {1u, 36u}}));
 }
 
 TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_InvalidType) {
diff --git a/src/reader/wgsl/parser_impl_type_alias_test.cc b/src/reader/wgsl/parser_impl_type_alias_test.cc
index 274d8a9..5f1e03d 100644
--- a/src/reader/wgsl/parser_impl_type_alias_test.cc
+++ b/src/reader/wgsl/parser_impl_type_alias_test.cc
@@ -29,9 +29,9 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::Alias>());
   auto* alias = t->As<ast::Alias>();
-  ASSERT_TRUE(alias->type()->Is<ast::I32>());
+  ASSERT_TRUE(alias->type->Is<ast::I32>());
 
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 13u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 13u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_ParsesStruct_Ident) {
@@ -47,9 +47,9 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t.value->Is<ast::Alias>());
   auto* alias = t.value->As<ast::Alias>();
-  EXPECT_EQ(p->builder().Symbols().NameFor(alias->symbol()), "a");
-  EXPECT_TRUE(alias->type()->Is<ast::TypeName>());
-  EXPECT_EQ(alias->source().range, (Source::Range{{1u, 1u}, {1u, 11u}}));
+  EXPECT_EQ(p->builder().Symbols().NameFor(alias->name), "a");
+  EXPECT_TRUE(alias->type->Is<ast::TypeName>());
+  EXPECT_EQ(alias->source.range, (Source::Range{{1u, 1u}, {1u, 11u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_MissingIdent) {
diff --git a/src/reader/wgsl/parser_impl_type_decl_test.cc b/src/reader/wgsl/parser_impl_type_decl_test.cc
index 4c3c266..2035359 100644
--- a/src/reader/wgsl/parser_impl_type_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_type_decl_test.cc
@@ -46,8 +46,8 @@
   ASSERT_NE(t.value, nullptr) << p->error();
   auto* type_name = t.value->As<ast::TypeName>();
   ASSERT_NE(type_name, nullptr);
-  EXPECT_EQ(p->builder().Symbols().Get("A"), type_name->name());
-  EXPECT_EQ(type_name->source().range, (Source::Range{{1u, 1u}, {1u, 2u}}));
+  EXPECT_EQ(p->builder().Symbols().Get("A"), type_name->name);
+  EXPECT_EQ(type_name->source.range, (Source::Range{{1u, 1u}, {1u, 2u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_Identifier_NotFound) {
@@ -69,7 +69,7 @@
   EXPECT_FALSE(t.errored);
   ASSERT_NE(t.value, nullptr) << p->error();
   ASSERT_TRUE(t.value->Is<ast::Bool>());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 5u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 5u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_F32) {
@@ -80,7 +80,7 @@
   EXPECT_FALSE(t.errored);
   ASSERT_NE(t.value, nullptr) << p->error();
   ASSERT_TRUE(t.value->Is<ast::F32>());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 4u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 4u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_I32) {
@@ -91,7 +91,7 @@
   EXPECT_FALSE(t.errored);
   ASSERT_NE(t.value, nullptr) << p->error();
   ASSERT_TRUE(t.value->Is<ast::I32>());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 4u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 4u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_U32) {
@@ -102,7 +102,7 @@
   EXPECT_FALSE(t.errored);
   ASSERT_NE(t.value, nullptr) << p->error();
   ASSERT_TRUE(t.value->Is<ast::U32>());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 4u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 4u}}));
 }
 
 struct VecData {
@@ -126,8 +126,8 @@
   ASSERT_NE(t.value, nullptr) << p->error();
   ASSERT_FALSE(p->has_error());
   EXPECT_TRUE(t.value->Is<ast::Vector>());
-  EXPECT_EQ(t.value->As<ast::Vector>()->size(), params.count);
-  EXPECT_EQ(t.value->source().range, params.range);
+  EXPECT_EQ(t.value->As<ast::Vector>()->width, params.count);
+  EXPECT_EQ(t.value->source.range, params.range);
 }
 INSTANTIATE_TEST_SUITE_P(
     ParserImplTest,
@@ -218,9 +218,9 @@
   ASSERT_TRUE(t.value->Is<ast::Pointer>());
 
   auto* ptr = t.value->As<ast::Pointer>();
-  ASSERT_TRUE(ptr->type()->Is<ast::F32>());
-  ASSERT_EQ(ptr->storage_class(), ast::StorageClass::kFunction);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 19u}}));
+  ASSERT_TRUE(ptr->type->Is<ast::F32>());
+  ASSERT_EQ(ptr->storage_class, ast::StorageClass::kFunction);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 19u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_Ptr_WithAccess) {
@@ -233,10 +233,10 @@
   ASSERT_TRUE(t.value->Is<ast::Pointer>());
 
   auto* ptr = t.value->As<ast::Pointer>();
-  ASSERT_TRUE(ptr->type()->Is<ast::F32>());
-  ASSERT_EQ(ptr->storage_class(), ast::StorageClass::kFunction);
-  ASSERT_EQ(ptr->access(), ast::Access::kRead);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 25u}}));
+  ASSERT_TRUE(ptr->type->Is<ast::F32>());
+  ASSERT_EQ(ptr->storage_class, ast::StorageClass::kFunction);
+  ASSERT_EQ(ptr->access, ast::Access::kRead);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 25u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_Ptr_ToVec) {
@@ -249,13 +249,13 @@
   ASSERT_TRUE(t.value->Is<ast::Pointer>());
 
   auto* ptr = t.value->As<ast::Pointer>();
-  ASSERT_TRUE(ptr->type()->Is<ast::Vector>());
-  ASSERT_EQ(ptr->storage_class(), ast::StorageClass::kFunction);
+  ASSERT_TRUE(ptr->type->Is<ast::Vector>());
+  ASSERT_EQ(ptr->storage_class, ast::StorageClass::kFunction);
 
-  auto* vec = ptr->type()->As<ast::Vector>();
-  ASSERT_EQ(vec->size(), 2u);
-  ASSERT_TRUE(vec->type()->Is<ast::F32>());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 25}}));
+  auto* vec = ptr->type->As<ast::Vector>();
+  ASSERT_EQ(vec->width, 2u);
+  ASSERT_TRUE(vec->type->Is<ast::F32>());
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 25}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_Ptr_MissingLessThan) {
@@ -388,8 +388,8 @@
   ASSERT_TRUE(t.value->Is<ast::Atomic>());
 
   auto* atomic = t.value->As<ast::Atomic>();
-  ASSERT_TRUE(atomic->type()->Is<ast::F32>());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 12u}}));
+  ASSERT_TRUE(atomic->type->Is<ast::F32>());
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 12u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_Atomic_ToVec) {
@@ -402,12 +402,12 @@
   ASSERT_TRUE(t.value->Is<ast::Atomic>());
 
   auto* atomic = t.value->As<ast::Atomic>();
-  ASSERT_TRUE(atomic->type()->Is<ast::Vector>());
+  ASSERT_TRUE(atomic->type->Is<ast::Vector>());
 
-  auto* vec = atomic->type()->As<ast::Vector>();
-  ASSERT_EQ(vec->size(), 2u);
-  ASSERT_TRUE(vec->type()->Is<ast::F32>());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 18u}}));
+  auto* vec = atomic->type->As<ast::Vector>();
+  ASSERT_EQ(vec->width, 2u);
+  ASSERT_TRUE(vec->type->Is<ast::F32>());
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 18u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_Atomic_MissingLessThan) {
@@ -451,15 +451,15 @@
 
   auto* a = t.value->As<ast::Array>();
   ASSERT_FALSE(a->IsRuntimeArray());
-  ASSERT_TRUE(a->type()->Is<ast::F32>());
-  EXPECT_EQ(a->decorations().size(), 0u);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 14u}}));
+  ASSERT_TRUE(a->type->Is<ast::F32>());
+  EXPECT_EQ(a->decorations.size(), 0u);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 14u}}));
 
-  auto* size_expr = a->Size()->As<ast::ScalarConstructorExpression>();
-  ASSERT_NE(size_expr, nullptr);
-  auto* size = size_expr->literal()->As<ast::SintLiteral>();
+  auto* count_expr = a->count->As<ast::ScalarConstructorExpression>();
+  ASSERT_NE(count_expr, nullptr);
+  auto* size = count_expr->literal->As<ast::SintLiteral>();
   ASSERT_NE(size, nullptr);
-  EXPECT_EQ(size->value_as_i32(), 5);
+  EXPECT_EQ(size->ValueAsI32(), 5);
 }
 
 TEST_F(ParserImplTest, TypeDecl_Array_UintLiteralSize) {
@@ -473,15 +473,15 @@
 
   auto* a = t.value->As<ast::Array>();
   ASSERT_FALSE(a->IsRuntimeArray());
-  ASSERT_TRUE(a->type()->Is<ast::F32>());
-  EXPECT_EQ(a->decorations().size(), 0u);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 15u}}));
+  ASSERT_TRUE(a->type->Is<ast::F32>());
+  EXPECT_EQ(a->decorations.size(), 0u);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 15u}}));
 
-  auto* size_expr = a->Size()->As<ast::ScalarConstructorExpression>();
-  ASSERT_NE(size_expr, nullptr);
-  auto* size = size_expr->literal()->As<ast::UintLiteral>();
+  auto* count_expr = a->count->As<ast::ScalarConstructorExpression>();
+  ASSERT_NE(count_expr, nullptr);
+  auto* size = count_expr->literal->As<ast::UintLiteral>();
   ASSERT_NE(size, nullptr);
-  EXPECT_EQ(size->value_as_u32(), 5u);
+  EXPECT_EQ(size->ValueAsU32(), 5u);
 }
 
 TEST_F(ParserImplTest, TypeDecl_Array_ConstantSize) {
@@ -495,13 +495,13 @@
 
   auto* a = t.value->As<ast::Array>();
   ASSERT_FALSE(a->IsRuntimeArray());
-  ASSERT_TRUE(a->type()->Is<ast::F32>());
-  EXPECT_EQ(a->decorations().size(), 0u);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 17u}}));
+  ASSERT_TRUE(a->type->Is<ast::F32>());
+  EXPECT_EQ(a->decorations.size(), 0u);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 17u}}));
 
-  auto* size_expr = a->Size()->As<ast::IdentifierExpression>();
-  ASSERT_NE(size_expr, nullptr);
-  EXPECT_EQ(p->builder().Symbols().NameFor(size_expr->symbol()), "size");
+  auto* count_expr = a->count->As<ast::IdentifierExpression>();
+  ASSERT_NE(count_expr, nullptr);
+  EXPECT_EQ(p->builder().Symbols().NameFor(count_expr->symbol), "size");
 }
 
 TEST_F(ParserImplTest, TypeDecl_Array_Stride) {
@@ -515,19 +515,19 @@
 
   auto* a = t.value->As<ast::Array>();
   ASSERT_FALSE(a->IsRuntimeArray());
-  ASSERT_TRUE(a->type()->Is<ast::F32>());
+  ASSERT_TRUE(a->type->Is<ast::F32>());
 
-  auto* size_expr = a->Size()->As<ast::ScalarConstructorExpression>();
-  ASSERT_NE(size_expr, nullptr);
-  auto* size = size_expr->literal()->As<ast::SintLiteral>();
+  auto* count_expr = a->count->As<ast::ScalarConstructorExpression>();
+  ASSERT_NE(count_expr, nullptr);
+  auto* size = count_expr->literal->As<ast::SintLiteral>();
   ASSERT_NE(size, nullptr);
-  EXPECT_EQ(size->value_as_i32(), 5);
+  EXPECT_EQ(size->ValueAsI32(), 5);
 
-  ASSERT_EQ(a->decorations().size(), 1u);
-  auto* stride = a->decorations()[0];
+  ASSERT_EQ(a->decorations.size(), 1u);
+  auto* stride = a->decorations[0];
   ASSERT_TRUE(stride->Is<ast::StrideDecoration>());
-  ASSERT_EQ(stride->As<ast::StrideDecoration>()->stride(), 16u);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 16u}, {1u, 29u}}));
+  ASSERT_EQ(stride->As<ast::StrideDecoration>()->stride, 16u);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 16u}, {1u, 29u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_Array_Runtime_Stride) {
@@ -541,13 +541,13 @@
 
   auto* a = t.value->As<ast::Array>();
   ASSERT_TRUE(a->IsRuntimeArray());
-  ASSERT_TRUE(a->type()->Is<ast::F32>());
+  ASSERT_TRUE(a->type->Is<ast::F32>());
 
-  ASSERT_EQ(a->decorations().size(), 1u);
-  auto* stride = a->decorations()[0];
+  ASSERT_EQ(a->decorations.size(), 1u);
+  auto* stride = a->decorations[0];
   ASSERT_TRUE(stride->Is<ast::StrideDecoration>());
-  ASSERT_EQ(stride->As<ast::StrideDecoration>()->stride(), 16u);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 16u}, {1u, 26u}}));
+  ASSERT_EQ(stride->As<ast::StrideDecoration>()->stride, 16u);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 16u}, {1u, 26u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_OneBlock) {
@@ -561,15 +561,15 @@
 
   auto* a = t.value->As<ast::Array>();
   ASSERT_TRUE(a->IsRuntimeArray());
-  ASSERT_TRUE(a->type()->Is<ast::F32>());
+  ASSERT_TRUE(a->type->Is<ast::F32>());
 
-  auto& decos = a->decorations();
+  auto& decos = a->decorations;
   ASSERT_EQ(decos.size(), 2u);
   EXPECT_TRUE(decos[0]->Is<ast::StrideDecoration>());
-  EXPECT_EQ(decos[0]->As<ast::StrideDecoration>()->stride(), 16u);
+  EXPECT_EQ(decos[0]->As<ast::StrideDecoration>()->stride, 16u);
   EXPECT_TRUE(decos[1]->Is<ast::StrideDecoration>());
-  EXPECT_EQ(decos[1]->As<ast::StrideDecoration>()->stride(), 32u);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 28u}, {1u, 38u}}));
+  EXPECT_EQ(decos[1]->As<ast::StrideDecoration>()->stride, 32u);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 28u}, {1u, 38u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_MultipleBlocks) {
@@ -583,15 +583,15 @@
 
   auto* a = t.value->As<ast::Array>();
   ASSERT_TRUE(a->IsRuntimeArray());
-  ASSERT_TRUE(a->type()->Is<ast::F32>());
+  ASSERT_TRUE(a->type->Is<ast::F32>());
 
-  auto& decos = a->decorations();
+  auto& decos = a->decorations;
   ASSERT_EQ(decos.size(), 2u);
   EXPECT_TRUE(decos[0]->Is<ast::StrideDecoration>());
-  EXPECT_EQ(decos[0]->As<ast::StrideDecoration>()->stride(), 16u);
+  EXPECT_EQ(decos[0]->As<ast::StrideDecoration>()->stride, 16u);
   EXPECT_TRUE(decos[1]->Is<ast::StrideDecoration>());
-  EXPECT_EQ(decos[1]->As<ast::StrideDecoration>()->stride(), 32u);
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 31u}, {1u, 41u}}));
+  EXPECT_EQ(decos[1]->As<ast::StrideDecoration>()->stride, 32u);
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 31u}, {1u, 41u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_Array_Decoration_MissingArray) {
@@ -687,8 +687,8 @@
 
   auto* a = t.value->As<ast::Array>();
   ASSERT_TRUE(a->IsRuntimeArray());
-  ASSERT_TRUE(a->type()->Is<ast::U32>());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 11u}}));
+  ASSERT_TRUE(a->type->Is<ast::U32>());
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 11u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_Array_Runtime_Vec) {
@@ -702,10 +702,10 @@
 
   auto* a = t.value->As<ast::Array>();
   ASSERT_TRUE(a->IsRuntimeArray());
-  ASSERT_TRUE(a->type()->Is<ast::Vector>());
-  EXPECT_EQ(a->type()->As<ast::Vector>()->size(), 4u);
-  EXPECT_TRUE(a->type()->As<ast::Vector>()->type()->Is<ast::U32>());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 17u}}));
+  ASSERT_TRUE(a->type->Is<ast::Vector>());
+  EXPECT_EQ(a->type->As<ast::Vector>()->width, 4u);
+  EXPECT_TRUE(a->type->As<ast::Vector>()->type->Is<ast::U32>());
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 17u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_Array_BadType) {
@@ -791,9 +791,9 @@
   ASSERT_FALSE(p->has_error());
   EXPECT_TRUE(t.value->Is<ast::Matrix>());
   auto* mat = t.value->As<ast::Matrix>();
-  EXPECT_EQ(mat->rows(), params.rows);
-  EXPECT_EQ(mat->columns(), params.columns);
-  EXPECT_EQ(t.value->source().range, params.range);
+  EXPECT_EQ(mat->rows, params.rows);
+  EXPECT_EQ(mat->columns, params.columns);
+  EXPECT_EQ(t.value->source.range, params.range);
 }
 INSTANTIATE_TEST_SUITE_P(
     ParserImplTest,
@@ -915,7 +915,7 @@
   ASSERT_NE(t.value, nullptr) << p->error();
   ASSERT_TRUE(t.value->Is<ast::Sampler>());
   ASSERT_FALSE(t.value->As<ast::Sampler>()->IsComparison());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 8u}}));
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 8u}}));
 }
 
 TEST_F(ParserImplTest, TypeDecl_Texture) {
@@ -927,8 +927,8 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t.value->Is<ast::Texture>());
   ASSERT_TRUE(t.value->Is<ast::SampledTexture>());
-  ASSERT_TRUE(t.value->As<ast::SampledTexture>()->type()->Is<ast::F32>());
-  EXPECT_EQ(t.value->source().range, (Source::Range{{1u, 1u}, {1u, 18u}}));
+  ASSERT_TRUE(t.value->As<ast::SampledTexture>()->type->Is<ast::F32>());
+  EXPECT_EQ(t.value->source.range, (Source::Range{{1u, 1u}, {1u, 18u}}));
 }
 
 }  // namespace
diff --git a/src/reader/wgsl/parser_impl_unary_expression_test.cc b/src/reader/wgsl/parser_impl_unary_expression_test.cc
index 0724c55..4627366 100644
--- a/src/reader/wgsl/parser_impl_unary_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_unary_expression_test.cc
@@ -30,15 +30,15 @@
 
   ASSERT_TRUE(e->Is<ast::ArrayAccessorExpression>());
   auto* ary = e->As<ast::ArrayAccessorExpression>();
-  ASSERT_TRUE(ary->array()->Is<ast::IdentifierExpression>());
-  auto* ident = ary->array()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_TRUE(ary->array->Is<ast::IdentifierExpression>());
+  auto* ident = ary->array->As<ast::IdentifierExpression>();
+  EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_TRUE(ary->idx_expr()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(ary->idx_expr()->Is<ast::ScalarConstructorExpression>());
-  auto* init = ary->idx_expr()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::SintLiteral>());
-  ASSERT_EQ(init->literal()->As<ast::SintLiteral>()->value(), 2);
+  ASSERT_TRUE(ary->index->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(ary->index->Is<ast::ScalarConstructorExpression>());
+  auto* init = ary->index->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
+  ASSERT_EQ(init->literal->As<ast::SintLiteral>()->value, 2);
 }
 
 TEST_F(ParserImplTest, UnaryExpression_Minus) {
@@ -51,14 +51,14 @@
   ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
 
   auto* u = e->As<ast::UnaryOpExpression>();
-  ASSERT_EQ(u->op(), ast::UnaryOp::kNegation);
+  ASSERT_EQ(u->op, ast::UnaryOp::kNegation);
 
-  ASSERT_TRUE(u->expr()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(u->expr()->Is<ast::ScalarConstructorExpression>());
+  ASSERT_TRUE(u->expr->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(u->expr->Is<ast::ScalarConstructorExpression>());
 
-  auto* init = u->expr()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::SintLiteral>());
-  EXPECT_EQ(init->literal()->As<ast::SintLiteral>()->value(), 1);
+  auto* init = u->expr->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
+  EXPECT_EQ(init->literal->As<ast::SintLiteral>()->value, 1);
 }
 
 TEST_F(ParserImplTest, UnaryExpression_AddressOf) {
@@ -71,8 +71,8 @@
   ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
 
   auto* u = e->As<ast::UnaryOpExpression>();
-  EXPECT_EQ(u->op(), ast::UnaryOp::kAddressOf);
-  EXPECT_TRUE(u->expr()->Is<ast::IdentifierExpression>());
+  EXPECT_EQ(u->op, ast::UnaryOp::kAddressOf);
+  EXPECT_TRUE(u->expr->Is<ast::IdentifierExpression>());
 }
 
 TEST_F(ParserImplTest, UnaryExpression_Dereference) {
@@ -85,8 +85,8 @@
   ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
 
   auto* u = e->As<ast::UnaryOpExpression>();
-  EXPECT_EQ(u->op(), ast::UnaryOp::kIndirection);
-  EXPECT_TRUE(u->expr()->Is<ast::IdentifierExpression>());
+  EXPECT_EQ(u->op, ast::UnaryOp::kIndirection);
+  EXPECT_TRUE(u->expr->Is<ast::IdentifierExpression>());
 }
 
 TEST_F(ParserImplTest, UnaryExpression_AddressOf_Precedence) {
@@ -99,8 +99,8 @@
   ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
 
   auto* u = e->As<ast::UnaryOpExpression>();
-  EXPECT_EQ(u->op(), ast::UnaryOp::kAddressOf);
-  EXPECT_TRUE(u->expr()->Is<ast::MemberAccessorExpression>());
+  EXPECT_EQ(u->op, ast::UnaryOp::kAddressOf);
+  EXPECT_TRUE(u->expr->Is<ast::MemberAccessorExpression>());
 }
 
 TEST_F(ParserImplTest, UnaryExpression_Dereference_Precedence) {
@@ -113,8 +113,8 @@
   ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
 
   auto* u = e->As<ast::UnaryOpExpression>();
-  EXPECT_EQ(u->op(), ast::UnaryOp::kIndirection);
-  EXPECT_TRUE(u->expr()->Is<ast::MemberAccessorExpression>());
+  EXPECT_EQ(u->op, ast::UnaryOp::kIndirection);
+  EXPECT_TRUE(u->expr->Is<ast::MemberAccessorExpression>());
 }
 
 TEST_F(ParserImplTest, UnaryExpression_Minus_InvalidRHS) {
@@ -137,14 +137,14 @@
   ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
 
   auto* u = e->As<ast::UnaryOpExpression>();
-  ASSERT_EQ(u->op(), ast::UnaryOp::kNot);
+  ASSERT_EQ(u->op, ast::UnaryOp::kNot);
 
-  ASSERT_TRUE(u->expr()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(u->expr()->Is<ast::ScalarConstructorExpression>());
+  ASSERT_TRUE(u->expr->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(u->expr->Is<ast::ScalarConstructorExpression>());
 
-  auto* init = u->expr()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::SintLiteral>());
-  EXPECT_EQ(init->literal()->As<ast::SintLiteral>()->value(), 1);
+  auto* init = u->expr->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
+  EXPECT_EQ(init->literal->As<ast::SintLiteral>()->value, 1);
 }
 
 TEST_F(ParserImplTest, UnaryExpression_Bang_InvalidRHS) {
@@ -167,14 +167,14 @@
   ASSERT_TRUE(e->Is<ast::UnaryOpExpression>());
 
   auto* u = e->As<ast::UnaryOpExpression>();
-  ASSERT_EQ(u->op(), ast::UnaryOp::kComplement);
+  ASSERT_EQ(u->op, ast::UnaryOp::kComplement);
 
-  ASSERT_TRUE(u->expr()->Is<ast::ConstructorExpression>());
-  ASSERT_TRUE(u->expr()->Is<ast::ScalarConstructorExpression>());
+  ASSERT_TRUE(u->expr->Is<ast::ConstructorExpression>());
+  ASSERT_TRUE(u->expr->Is<ast::ScalarConstructorExpression>());
 
-  auto* init = u->expr()->As<ast::ScalarConstructorExpression>();
-  ASSERT_TRUE(init->literal()->Is<ast::SintLiteral>());
-  EXPECT_EQ(init->literal()->As<ast::SintLiteral>()->value(), 1);
+  auto* init = u->expr->As<ast::ScalarConstructorExpression>();
+  ASSERT_TRUE(init->literal->Is<ast::SintLiteral>());
+  EXPECT_EQ(init->literal->As<ast::SintLiteral>()->value, 1);
 }
 
 TEST_F(ParserImplTest, UnaryExpression_PrefixPlusPlus) {
diff --git a/src/reader/wgsl/parser_impl_variable_decl_test.cc b/src/reader/wgsl/parser_impl_variable_decl_test.cc
index efb91d8..97bffb1 100644
--- a/src/reader/wgsl/parser_impl_variable_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_decl_test.cc
@@ -30,7 +30,7 @@
   EXPECT_TRUE(v->type->Is<ast::F32>());
 
   EXPECT_EQ(v->source.range, (Source::Range{{1u, 5u}, {1u, 11u}}));
-  EXPECT_EQ(v->type->source().range, (Source::Range{{1u, 14u}, {1u, 17u}}));
+  EXPECT_EQ(v->type->source.range, (Source::Range{{1u, 14u}, {1u, 17u}}));
 }
 
 TEST_F(ParserImplTest, VariableDecl_Inferred_Parses) {
diff --git a/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc b/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc
index c265efb..5493345 100644
--- a/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_decoration_list_test.cc
@@ -33,9 +33,9 @@
   ASSERT_NE(deco_1, nullptr);
 
   ASSERT_TRUE(deco_0->Is<ast::LocationDecoration>());
-  EXPECT_EQ(deco_0->As<ast::LocationDecoration>()->value(), 4u);
+  EXPECT_EQ(deco_0->As<ast::LocationDecoration>()->value, 4u);
   ASSERT_TRUE(deco_1->Is<ast::BuiltinDecoration>());
-  EXPECT_EQ(deco_1->As<ast::BuiltinDecoration>()->value(),
+  EXPECT_EQ(deco_1->As<ast::BuiltinDecoration>()->builtin,
             ast::Builtin::kPosition);
 }
 
diff --git a/src/reader/wgsl/parser_impl_variable_decoration_test.cc b/src/reader/wgsl/parser_impl_variable_decoration_test.cc
index a805f6b..e04103b 100644
--- a/src/reader/wgsl/parser_impl_variable_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_decoration_test.cc
@@ -31,7 +31,7 @@
   ASSERT_TRUE(var_deco->Is<ast::LocationDecoration>());
 
   auto* loc = var_deco->As<ast::LocationDecoration>();
-  EXPECT_EQ(loc->value(), 4u);
+  EXPECT_EQ(loc->value, 4u);
 }
 
 TEST_F(ParserImplTest, Decoration_Location_MissingLeftParen) {
@@ -101,7 +101,7 @@
   ASSERT_TRUE(var_deco->Is<ast::BuiltinDecoration>());
 
   auto* builtin = var_deco->As<ast::BuiltinDecoration>();
-  EXPECT_EQ(builtin->value(), params.result);
+  EXPECT_EQ(builtin->builtin, params.result);
 }
 INSTANTIATE_TEST_SUITE_P(
     ParserImplTest,
@@ -185,8 +185,8 @@
   ASSERT_TRUE(var_deco->Is<ast::InterpolateDecoration>());
 
   auto* interp = var_deco->As<ast::InterpolateDecoration>();
-  EXPECT_EQ(interp->type(), ast::InterpolationType::kFlat);
-  EXPECT_EQ(interp->sampling(), ast::InterpolationSampling::kNone);
+  EXPECT_EQ(interp->type, ast::InterpolationType::kFlat);
+  EXPECT_EQ(interp->sampling, ast::InterpolationSampling::kNone);
 }
 
 TEST_F(ParserImplTest, Decoration_Interpolate_Perspective_Center) {
@@ -201,8 +201,8 @@
   ASSERT_TRUE(var_deco->Is<ast::InterpolateDecoration>());
 
   auto* interp = var_deco->As<ast::InterpolateDecoration>();
-  EXPECT_EQ(interp->type(), ast::InterpolationType::kPerspective);
-  EXPECT_EQ(interp->sampling(), ast::InterpolationSampling::kCenter);
+  EXPECT_EQ(interp->type, ast::InterpolationType::kPerspective);
+  EXPECT_EQ(interp->sampling, ast::InterpolationSampling::kCenter);
 }
 
 TEST_F(ParserImplTest, Decoration_Interpolate_Perspective_Centroid) {
@@ -217,8 +217,8 @@
   ASSERT_TRUE(var_deco->Is<ast::InterpolateDecoration>());
 
   auto* interp = var_deco->As<ast::InterpolateDecoration>();
-  EXPECT_EQ(interp->type(), ast::InterpolationType::kPerspective);
-  EXPECT_EQ(interp->sampling(), ast::InterpolationSampling::kCentroid);
+  EXPECT_EQ(interp->type, ast::InterpolationType::kPerspective);
+  EXPECT_EQ(interp->sampling, ast::InterpolationSampling::kCentroid);
 }
 
 TEST_F(ParserImplTest, Decoration_Interpolate_Linear_Sample) {
@@ -233,8 +233,8 @@
   ASSERT_TRUE(var_deco->Is<ast::InterpolateDecoration>());
 
   auto* interp = var_deco->As<ast::InterpolateDecoration>();
-  EXPECT_EQ(interp->type(), ast::InterpolationType::kLinear);
-  EXPECT_EQ(interp->sampling(), ast::InterpolationSampling::kSample);
+  EXPECT_EQ(interp->type, ast::InterpolationType::kLinear);
+  EXPECT_EQ(interp->sampling, ast::InterpolationSampling::kSample);
 }
 
 TEST_F(ParserImplTest, Decoration_Interpolate_MissingLeftParen) {
@@ -309,7 +309,7 @@
   ASSERT_TRUE(var_deco->Is<ast::BindingDecoration>());
 
   auto* binding = var_deco->As<ast::BindingDecoration>();
-  EXPECT_EQ(binding->value(), 4u);
+  EXPECT_EQ(binding->value, 4u);
 }
 
 TEST_F(ParserImplTest, Decoration_Binding_MissingLeftParen) {
@@ -366,7 +366,7 @@
   ASSERT_TRUE(var_deco->Is<ast::GroupDecoration>());
 
   auto* group = var_deco->As<ast::GroupDecoration>();
-  EXPECT_EQ(group->value(), 4u);
+  EXPECT_EQ(group->value, 4u);
 }
 
 TEST_F(ParserImplTest, Decoration_Group_MissingLeftParen) {
diff --git a/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc b/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc
index a063a61..0cf6a31 100644
--- a/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc
@@ -30,7 +30,7 @@
   ASSERT_TRUE(decl->type->Is<ast::F32>());
 
   EXPECT_EQ(decl->source.range, (Source::Range{{1u, 1u}, {1u, 7u}}));
-  EXPECT_EQ(decl->type->source().range, (Source::Range{{1u, 10u}, {1u, 13u}}));
+  EXPECT_EQ(decl->type->source.range, (Source::Range{{1u, 10u}, {1u, 13u}}));
 }
 
 TEST_F(ParserImplTest, VariableIdentDecl_Inferred_Parses) {
diff --git a/src/reader/wgsl/parser_impl_variable_stmt_test.cc b/src/reader/wgsl/parser_impl_variable_stmt_test.cc
index ee6536c..d9ec4ad 100644
--- a/src/reader/wgsl/parser_impl_variable_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_stmt_test.cc
@@ -27,15 +27,15 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
-  ASSERT_NE(e->variable(), nullptr);
-  EXPECT_EQ(e->variable()->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_NE(e->variable, nullptr);
+  EXPECT_EQ(e->variable->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_EQ(e->source().range.begin.line, 1u);
-  ASSERT_EQ(e->source().range.begin.column, 5u);
-  ASSERT_EQ(e->source().range.end.line, 1u);
-  ASSERT_EQ(e->source().range.end.column, 6u);
+  ASSERT_EQ(e->source.range.begin.line, 1u);
+  ASSERT_EQ(e->source.range.begin.column, 5u);
+  ASSERT_EQ(e->source.range.end.line, 1u);
+  ASSERT_EQ(e->source.range.end.column, 6u);
 
-  EXPECT_EQ(e->variable()->constructor(), nullptr);
+  EXPECT_EQ(e->variable->constructor, nullptr);
 }
 
 TEST_F(ParserImplTest, VariableStmt_VariableDecl_WithInit) {
@@ -46,16 +46,16 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
-  ASSERT_NE(e->variable(), nullptr);
-  EXPECT_EQ(e->variable()->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_NE(e->variable, nullptr);
+  EXPECT_EQ(e->variable->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_EQ(e->source().range.begin.line, 1u);
-  ASSERT_EQ(e->source().range.begin.column, 5u);
-  ASSERT_EQ(e->source().range.end.line, 1u);
-  ASSERT_EQ(e->source().range.end.column, 6u);
+  ASSERT_EQ(e->source.range.begin.line, 1u);
+  ASSERT_EQ(e->source.range.begin.column, 5u);
+  ASSERT_EQ(e->source.range.end.line, 1u);
+  ASSERT_EQ(e->source.range.end.column, 6u);
 
-  ASSERT_NE(e->variable()->constructor(), nullptr);
-  EXPECT_TRUE(e->variable()->constructor()->Is<ast::ConstructorExpression>());
+  ASSERT_NE(e->variable->constructor, nullptr);
+  EXPECT_TRUE(e->variable->constructor->Is<ast::ConstructorExpression>());
 }
 
 TEST_F(ParserImplTest, VariableStmt_VariableDecl_Invalid) {
@@ -86,11 +86,11 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
-  ASSERT_NE(e->variable(), nullptr);
-  EXPECT_EQ(e->variable()->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_NE(e->variable, nullptr);
+  EXPECT_EQ(e->variable->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_NE(e->variable()->constructor(), nullptr);
-  EXPECT_TRUE(e->variable()->constructor()->Is<ast::ConstructorExpression>());
+  ASSERT_NE(e->variable->constructor, nullptr);
+  EXPECT_TRUE(e->variable->constructor->Is<ast::ConstructorExpression>());
 }
 
 TEST_F(ParserImplTest, VariableStmt_VariableDecl_ArrayInit_NoSpace) {
@@ -101,11 +101,11 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
-  ASSERT_NE(e->variable(), nullptr);
-  EXPECT_EQ(e->variable()->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_NE(e->variable, nullptr);
+  EXPECT_EQ(e->variable->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_NE(e->variable()->constructor(), nullptr);
-  EXPECT_TRUE(e->variable()->constructor()->Is<ast::ConstructorExpression>());
+  ASSERT_NE(e->variable->constructor, nullptr);
+  EXPECT_TRUE(e->variable->constructor->Is<ast::ConstructorExpression>());
 }
 
 TEST_F(ParserImplTest, VariableStmt_VariableDecl_VecInit) {
@@ -116,11 +116,11 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
-  ASSERT_NE(e->variable(), nullptr);
-  EXPECT_EQ(e->variable()->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_NE(e->variable, nullptr);
+  EXPECT_EQ(e->variable->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_NE(e->variable()->constructor(), nullptr);
-  EXPECT_TRUE(e->variable()->constructor()->Is<ast::ConstructorExpression>());
+  ASSERT_NE(e->variable->constructor, nullptr);
+  EXPECT_TRUE(e->variable->constructor->Is<ast::ConstructorExpression>());
 }
 
 TEST_F(ParserImplTest, VariableStmt_VariableDecl_VecInit_NoSpace) {
@@ -131,11 +131,11 @@
   EXPECT_FALSE(p->has_error()) << p->error();
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
-  ASSERT_NE(e->variable(), nullptr);
-  EXPECT_EQ(e->variable()->symbol(), p->builder().Symbols().Get("a"));
+  ASSERT_NE(e->variable, nullptr);
+  EXPECT_EQ(e->variable->symbol, p->builder().Symbols().Get("a"));
 
-  ASSERT_NE(e->variable()->constructor(), nullptr);
-  EXPECT_TRUE(e->variable()->constructor()->Is<ast::ConstructorExpression>());
+  ASSERT_NE(e->variable->constructor, nullptr);
+  EXPECT_TRUE(e->variable->constructor->Is<ast::ConstructorExpression>());
 }
 
 TEST_F(ParserImplTest, VariableStmt_Let) {
@@ -147,10 +147,10 @@
   ASSERT_NE(e.value, nullptr);
   ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
 
-  ASSERT_EQ(e->source().range.begin.line, 1u);
-  ASSERT_EQ(e->source().range.begin.column, 5u);
-  ASSERT_EQ(e->source().range.end.line, 1u);
-  ASSERT_EQ(e->source().range.end.column, 6u);
+  ASSERT_EQ(e->source.range.begin.line, 1u);
+  ASSERT_EQ(e->source.range.begin.column, 5u);
+  ASSERT_EQ(e->source.range.end.line, 1u);
+  ASSERT_EQ(e->source.range.end.column, 6u);
 }
 
 TEST_F(ParserImplTest, VariableStmt_Let_InvalidVarIdent) {
diff --git a/src/resolver/inferred_type_test.cc b/src/resolver/inferred_type_test.cc
index c625b64..b194e14 100644
--- a/src/resolver/inferred_type_test.cc
+++ b/src/resolver/inferred_type_test.cc
@@ -157,9 +157,9 @@
   auto* str = Structure("S", {member}, {create<ast::StructBlockDecoration>()});
 
   auto* expected_type = create<sem::Struct>(
-      str, str->name(),
+      str, str->name,
       sem::StructMemberList{create<sem::StructMember>(
-          member, member->symbol(), create<sem::I32>(), 0, 0, 0, 4)},
+          member, member->symbol, create<sem::I32>(), 0, 0, 0, 4)},
       0, 4, 4);
 
   auto* ctor_expr = Construct(ty.Of(str));
diff --git a/src/resolver/intrinsic_test.cc b/src/resolver/intrinsic_test.cc
index 5e6526a..677b64a 100644
--- a/src/resolver/intrinsic_test.cc
+++ b/src/resolver/intrinsic_test.cc
@@ -1925,8 +1925,8 @@
 TEST_P(ResolverIntrinsicTest_Texture, Call) {
   auto param = GetParam();
 
-  param.buildTextureVariable(this);
-  param.buildSamplerVariable(this);
+  param.BuildTextureVariable(this);
+  param.BuildSamplerVariable(this);
 
   auto* call = Call(param.function, param.args(this));
   auto* stmt = ast::intrinsic::test::ReturnsVoid(param.overload)
diff --git a/src/resolver/intrinsic_validation_test.cc b/src/resolver/intrinsic_validation_test.cc
index 77b7e94..b41c1ce 100644
--- a/src/resolver/intrinsic_validation_test.cc
+++ b/src/resolver/intrinsic_validation_test.cc
@@ -125,8 +125,8 @@
   auto& p = GetParam();
   auto param = std::get<0>(p);
   auto offset = std::get<1>(p);
-  param.buildTextureVariable(this);
-  param.buildSamplerVariable(this);
+  param.BuildTextureVariable(this);
+  param.BuildSamplerVariable(this);
 
   auto args = param.args(this);
   // Make Resolver visit the Node about to be removed
@@ -160,8 +160,8 @@
   auto& p = GetParam();
   auto param = std::get<0>(p);
   auto offset = std::get<1>(p);
-  param.buildTextureVariable(this);
-  param.buildSamplerVariable(this);
+  param.BuildTextureVariable(this);
+  param.BuildSamplerVariable(this);
 
   auto args = param.args(this);
   // Make Resolver visit the Node about to be removed
@@ -192,8 +192,8 @@
 TEST_P(IntrinsicTextureSamplerValidationTest, EmptyVectorConstructor) {
   auto& p = GetParam();
   auto param = std::get<0>(p);
-  param.buildTextureVariable(this);
-  param.buildSamplerVariable(this);
+  param.BuildTextureVariable(this);
+  param.BuildSamplerVariable(this);
 
   auto args = param.args(this);
   // Make Resolver visit the Node about to be removed
@@ -215,8 +215,8 @@
   auto& p = GetParam();
   auto param = std::get<0>(p);
   auto offset = std::get<1>(p);
-  param.buildTextureVariable(this);
-  param.buildSamplerVariable(this);
+  param.BuildTextureVariable(this);
+  param.BuildSamplerVariable(this);
 
   auto args = param.args(this);
   // Make Resolver visit the Node about to be removed
@@ -245,8 +245,8 @@
   auto& p = GetParam();
   auto param = std::get<0>(p);
   auto offset = std::get<1>(p);
-  param.buildTextureVariable(this);
-  param.buildSamplerVariable(this);
+  param.BuildTextureVariable(this);
+  param.BuildSamplerVariable(this);
   auto* x = Const("x", ty.i32(), Construct(ty.i32(), offset.x));
 
   auto args = param.args(this);
diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc
index 75b4a82..19f461a 100644
--- a/src/resolver/resolver.cc
+++ b/src/resolver/resolver.cc
@@ -125,7 +125,7 @@
                           ast::DisabledValidation validation) {
   for (auto* decoration : decorations) {
     if (auto* dv = decoration->As<ast::DisableValidationDecoration>()) {
-      if (dv->Validation() == validation) {
+      if (dv->validation == validation) {
         return true;
       }
     }
@@ -145,9 +145,9 @@
 std::string deco_to_str(const ast::Decoration* deco) {
   std::stringstream str;
   if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
-    str << "builtin(" << builtin->value() << ")";
+    str << "builtin(" << builtin->builtin << ")";
   } else if (auto* location = deco->As<ast::LocationDecoration>()) {
-    str << "location(" << location->value() << ")";
+    str << "location(" << location->value << ")";
   }
   return str.str();
 }
@@ -275,7 +275,7 @@
     if (marked_.count(node) == 0) {
       TINT_ICE(Resolver, diagnostics_) << "AST node '" << node->TypeInfo().name
                                        << "' was not reached by the resolver\n"
-                                       << "At: " << node->source() << "\n"
+                                       << "At: " << node->source << "\n"
                                        << "Pointer: " << node;
       result = false;
     }
@@ -303,10 +303,10 @@
       return builder_->create<sem::F32>();
     }
     if (auto* t = ty->As<ast::Vector>()) {
-      if (auto* el = Type(t->type())) {
+      if (auto* el = Type(t->type)) {
         if (auto* vector = builder_->create<sem::Vector>(
-                const_cast<sem::Type*>(el), t->size())) {
-          if (ValidateVector(vector, t->source())) {
+                const_cast<sem::Type*>(el), t->width)) {
+          if (ValidateVector(vector, t->source)) {
             return vector;
           }
         }
@@ -314,12 +314,12 @@
       return nullptr;
     }
     if (auto* t = ty->As<ast::Matrix>()) {
-      if (auto* el = Type(t->type())) {
+      if (auto* el = Type(t->type)) {
         if (auto* column_type = builder_->create<sem::Vector>(
-                const_cast<sem::Type*>(el), t->rows())) {
+                const_cast<sem::Type*>(el), t->rows)) {
           if (auto* matrix =
-                  builder_->create<sem::Matrix>(column_type, t->columns())) {
-            if (ValidateMatrix(matrix, t->source())) {
+                  builder_->create<sem::Matrix>(column_type, t->columns)) {
+            if (ValidateMatrix(matrix, t->source)) {
               return matrix;
             }
           }
@@ -331,7 +331,7 @@
       return Array(t);
     }
     if (auto* t = ty->As<ast::Atomic>()) {
-      if (auto* el = Type(t->type())) {
+      if (auto* el = Type(t->type)) {
         auto* a = builder_->create<sem::Atomic>(const_cast<sem::Type*>(el));
         if (!ValidateAtomic(t, a)) {
           return nullptr;
@@ -341,47 +341,46 @@
       return nullptr;
     }
     if (auto* t = ty->As<ast::Pointer>()) {
-      if (auto* el = Type(t->type())) {
-        auto access = t->access();
+      if (auto* el = Type(t->type)) {
+        auto access = t->access;
         if (access == ast::kUndefined) {
-          access = DefaultAccessForStorageClass(t->storage_class());
+          access = DefaultAccessForStorageClass(t->storage_class);
         }
         return builder_->create<sem::Pointer>(const_cast<sem::Type*>(el),
-                                              t->storage_class(), access);
+                                              t->storage_class, access);
       }
       return nullptr;
     }
     if (auto* t = ty->As<ast::Sampler>()) {
-      return builder_->create<sem::Sampler>(t->kind());
+      return builder_->create<sem::Sampler>(t->kind);
     }
     if (auto* t = ty->As<ast::SampledTexture>()) {
-      if (auto* el = Type(t->type())) {
+      if (auto* el = Type(t->type)) {
         return builder_->create<sem::SampledTexture>(
-            t->dim(), const_cast<sem::Type*>(el));
+            t->dim, const_cast<sem::Type*>(el));
       }
       return nullptr;
     }
     if (auto* t = ty->As<ast::MultisampledTexture>()) {
-      if (auto* el = Type(t->type())) {
+      if (auto* el = Type(t->type)) {
         return builder_->create<sem::MultisampledTexture>(
-            t->dim(), const_cast<sem::Type*>(el));
+            t->dim, const_cast<sem::Type*>(el));
       }
       return nullptr;
     }
     if (auto* t = ty->As<ast::DepthTexture>()) {
-      return builder_->create<sem::DepthTexture>(t->dim());
+      return builder_->create<sem::DepthTexture>(t->dim);
     }
     if (auto* t = ty->As<ast::DepthMultisampledTexture>()) {
-      return builder_->create<sem::DepthMultisampledTexture>(t->dim());
+      return builder_->create<sem::DepthMultisampledTexture>(t->dim);
     }
     if (auto* t = ty->As<ast::StorageTexture>()) {
-      if (auto* el = Type(t->type())) {
+      if (auto* el = Type(t->type)) {
         if (!ValidateStorageTexture(t)) {
           return nullptr;
         }
         return builder_->create<sem::StorageTexture>(
-            t->dim(), t->image_format(), t->access(),
-            const_cast<sem::Type*>(el));
+            t->dim, t->format, t->access, const_cast<sem::Type*>(el));
       }
       return nullptr;
     }
@@ -389,11 +388,10 @@
       return builder_->create<sem::ExternalTexture>();
     }
     if (auto* t = ty->As<ast::TypeName>()) {
-      auto it = named_type_info_.find(t->name());
+      auto it = named_type_info_.find(t->name);
       if (it == named_type_info_.end()) {
-        AddError(
-            "unknown type '" + builder_->Symbols().NameFor(t->name()) + "'",
-            t->source());
+        AddError("unknown type '" + builder_->Symbols().NameFor(t->name) + "'",
+                 t->source);
         return nullptr;
       }
       return it->second.sem;
@@ -414,36 +412,36 @@
   // T must be either u32 or i32.
   if (!s->Type()->IsAnyOf<sem::U32, sem::I32>()) {
     AddError("atomic only supports i32 or u32 types",
-             a->type() ? a->type()->source() : a->source());
+             a->type ? a->type->source : a->source);
     return false;
   }
   return true;
 }
 
 bool Resolver::ValidateStorageTexture(const ast::StorageTexture* t) {
-  switch (t->access()) {
+  switch (t->access) {
     case ast::Access::kWrite:
       break;
     case ast::Access::kUndefined:
-      AddError("storage texture missing access control", t->source());
+      AddError("storage texture missing access control", t->source);
       return false;
     default:
       AddError("storage textures currently only support 'write' access control",
-               t->source());
+               t->source);
       return false;
   }
 
-  if (!IsValidStorageTextureDimension(t->dim())) {
+  if (!IsValidStorageTextureDimension(t->dim)) {
     AddError("cube dimensions for storage textures are not supported",
-             t->source());
+             t->source);
     return false;
   }
 
-  if (!IsValidStorageTextureImageFormat(t->image_format())) {
+  if (!IsValidStorageTextureImageFormat(t->format)) {
     AddError(
         "image format must be one of the texel formats specified for storage "
         "textues in https://gpuweb.github.io/gpuweb/wgsl/#texel-formats",
-        t->source());
+        t->source);
     return false;
   }
   return true;
@@ -454,7 +452,7 @@
                                            uint32_t index /* = 0 */) {
   if (variable_to_info_.count(var)) {
     TINT_ICE(Resolver, diagnostics_)
-        << "Variable " << builder_->Symbols().NameFor(var->symbol())
+        << "Variable " << builder_->Symbols().NameFor(var->symbol)
         << " already resolved";
     return nullptr;
   }
@@ -463,7 +461,7 @@
   const sem::Type* storage_type = nullptr;
 
   // If the variable has a declared type, resolve it.
-  if (auto* ty = var->type()) {
+  if (auto* ty = var->type) {
     type_name = ty->FriendlyName(builder_->Symbols());
     storage_type = Type(ty);
     if (!storage_type) {
@@ -475,9 +473,9 @@
   const sem::Type* rhs_type = nullptr;
 
   // Does the variable have a constructor?
-  if (auto* ctor = var->constructor()) {
-    Mark(var->constructor());
-    if (!Expression(var->constructor())) {
+  if (auto* ctor = var->constructor) {
+    Mark(var->constructor);
+    if (!Expression(var->constructor)) {
       return nullptr;
     }
 
@@ -490,37 +488,37 @@
 
     // If the variable has no declared type, infer it from the RHS
     if (!storage_type) {
-      if (!var->is_const() && kind == VariableKind::kGlobal) {
-        AddError("global var declaration must specify a type", var->source());
+      if (!var->is_const && kind == VariableKind::kGlobal) {
+        AddError("global var declaration must specify a type", var->source);
         return nullptr;
       }
 
       type_name = rhs_type_name;
       storage_type = rhs_type->UnwrapRef();  // Implicit load of RHS
     }
-  } else if (var->is_const() && kind != VariableKind::kParameter &&
-             !ast::HasDecoration<ast::OverrideDecoration>(var->decorations())) {
-    AddError("let declaration must have an initializer", var->source());
+  } else if (var->is_const && kind != VariableKind::kParameter &&
+             !ast::HasDecoration<ast::OverrideDecoration>(var->decorations)) {
+    AddError("let declaration must have an initializer", var->source);
     return nullptr;
-  } else if (!var->type()) {
+  } else if (!var->type) {
     AddError(
         (kind == VariableKind::kGlobal)
             ? "module scope var declaration requires a type and initializer"
             : "function scope var declaration requires a type or initializer",
-        var->source());
+        var->source);
     return nullptr;
   }
 
   if (!storage_type) {
     TINT_ICE(Resolver, diagnostics_)
         << "failed to determine storage type for variable '" +
-               builder_->Symbols().NameFor(var->symbol()) + "'\n"
-        << "Source: " << var->source();
+               builder_->Symbols().NameFor(var->symbol) + "'\n"
+        << "Source: " << var->source;
     return nullptr;
   }
 
-  auto storage_class = var->declared_storage_class();
-  if (storage_class == ast::StorageClass::kNone && !var->is_const()) {
+  auto storage_class = var->declared_storage_class;
+  if (storage_class == ast::StorageClass::kNone && !var->is_const) {
     // No declared storage class. Infer from usage / type.
     if (kind == VariableKind::kLocal) {
       storage_class = ast::StorageClass::kFunction;
@@ -533,13 +531,13 @@
     }
   }
 
-  auto access = var->declared_access();
+  auto access = var->declared_access;
   if (access == ast::Access::kUndefined) {
     access = DefaultAccessForStorageClass(storage_class);
   }
 
   auto* type = storage_type;
-  if (!var->is_const()) {
+  if (!var->is_const) {
     // Variable declaration. Unlike `let`, `var` has storage.
     // Variables are always of a reference type to the declared storage type.
     type =
@@ -588,14 +586,14 @@
       continue;
     }
     auto* override_deco =
-        ast::GetDecoration<ast::OverrideDecoration>(var->decorations());
+        ast::GetDecoration<ast::OverrideDecoration>(var->decorations);
     if (!override_deco) {
       continue;
     }
 
     uint16_t constant_id;
-    if (override_deco->HasValue()) {
-      constant_id = static_cast<uint16_t>(override_deco->value());
+    if (override_deco->has_value) {
+      constant_id = static_cast<uint16_t>(override_deco->value);
     } else {
       // No ID was specified, so allocate the next available ID.
       constant_id = next_constant_id;
@@ -624,14 +622,14 @@
 
   // Value type has to match storage type
   if (storage_type != value_type) {
-    std::string decl = var->is_const() ? "let" : "var";
+    std::string decl = var->is_const ? "let" : "var";
     AddError("cannot initialize " + decl + " of type '" + type_name +
                  "' with value of type '" + rhs_type_name + "'",
-             var->source());
+             var->source);
     return false;
   }
 
-  if (!var->is_const()) {
+  if (!var->is_const) {
     switch (storage_class) {
       case ast::StorageClass::kPrivate:
       case ast::StorageClass::kFunction:
@@ -641,11 +639,11 @@
         // Optionally has an initializer expression, if the variable is in the
         // private or function storage classes.
         AddError("var of storage class '" +
-                     std::string(ast::str(storage_class)) +
+                     std::string(ast::ToString(storage_class)) +
                      "' cannot have an initializer. var initializers are only "
                      "supported for the storage classes "
                      "'private' and 'function'",
-                 var->source());
+                 var->source);
         return false;
     }
   }
@@ -654,7 +652,7 @@
 }
 
 bool Resolver::GlobalVariable(ast::Variable* var) {
-  if (!ValidateNoDuplicateDefinition(var->symbol(), var->source(),
+  if (!ValidateNoDuplicateDefinition(var->symbol, var->source,
                                      /* check_global_scope_only */ true)) {
     return false;
   }
@@ -663,34 +661,34 @@
   if (!info) {
     return false;
   }
-  variable_stack_.set_global(var->symbol(), info);
+  variable_stack_.set_global(var->symbol, info);
 
-  if (!var->is_const() && info->storage_class == ast::StorageClass::kNone) {
-    AddError("global variables must have a storage class", var->source());
+  if (!var->is_const && info->storage_class == ast::StorageClass::kNone) {
+    AddError("global variables must have a storage class", var->source);
     return false;
   }
-  if (var->is_const() && !(info->storage_class == ast::StorageClass::kNone)) {
-    AddError("global constants shouldn't have a storage class", var->source());
+  if (var->is_const && !(info->storage_class == ast::StorageClass::kNone)) {
+    AddError("global constants shouldn't have a storage class", var->source);
     return false;
   }
 
-  for (auto* deco : var->decorations()) {
+  for (auto* deco : var->decorations) {
     Mark(deco);
 
     if (auto* override_deco = deco->As<ast::OverrideDecoration>()) {
       // Track the constant IDs that are specified in the shader.
-      if (override_deco->HasValue()) {
-        constant_ids_.emplace(override_deco->value(), info);
+      if (override_deco->has_value) {
+        constant_ids_.emplace(override_deco->value, info);
       }
     }
   }
 
-  if (!ValidateNoDuplicateDecorations(var->decorations())) {
+  if (!ValidateNoDuplicateDecorations(var->decorations)) {
     return false;
   }
 
-  if (auto bp = var->binding_point()) {
-    info->binding_point = {bp.group->value(), bp.binding->value()};
+  if (auto bp = var->BindingPoint()) {
+    info->binding_point = {bp.group->value, bp.binding->value};
   }
 
   if (!ValidateGlobalVariable(info)) {
@@ -699,10 +697,10 @@
 
   if (!ApplyStorageClassUsageToType(
           info->storage_class, const_cast<sem::Type*>(info->type->UnwrapRef()),
-          var->source())) {
+          var->source)) {
     AddNote("while instantiating variable " +
-                builder_->Symbols().NameFor(var->symbol()),
-            var->source());
+                builder_->Symbols().NameFor(var->symbol),
+            var->source);
     return false;
   }
 
@@ -738,11 +736,11 @@
   };
 
   auto member_name_of = [this](const sem::StructMember* sm) {
-    return builder_->Symbols().NameFor(sm->Declaration()->symbol());
+    return builder_->Symbols().NameFor(sm->Declaration()->symbol);
   };
 
   auto type_name_of = [this](const sem::StructMember* sm) {
-    return sm->Declaration()->type()->FriendlyName(builder_->Symbols());
+    return sm->Declaration()->type->FriendlyName(builder_->Symbols());
   };
 
   // TODO(amaiorano): Output struct and member decorations so that this output
@@ -833,21 +831,21 @@
     // Validate that member is at a valid byte offset
     if (m->Offset() % required_align != 0) {
       AddError("the offset of a struct member of type '" + type_name_of(m) +
-                   "' in storage class '" + ast::str(sc) +
+                   "' in storage class '" + ast::ToString(sc) +
                    "' must be a multiple of " + std::to_string(required_align) +
                    " bytes, but '" + member_name_of(m) +
                    "' is currently at offset " + std::to_string(m->Offset()) +
                    ". Consider setting [[align(" +
                    std::to_string(required_align) + ")]] on this member",
-               m->Declaration()->source());
+               m->Declaration()->source);
 
       AddNote("see layout of struct:\n" + get_struct_layout_string(str),
-              str->Declaration()->source());
+              str->Declaration()->source);
 
       if (auto* member_str = m->Type()->As<sem::Struct>()) {
         AddNote("and layout of struct member:\n" +
                     get_struct_layout_string(member_str),
-                member_str->Declaration()->source());
+                member_str->Declaration()->source);
       }
 
       return false;
@@ -866,15 +864,15 @@
                 std::to_string(prev_to_curr_offset) + " bytes between '" +
                 member_name_of(prev_member) + "' and '" + member_name_of(m) +
                 "'. Consider setting [[align(16)]] on this member",
-            m->Declaration()->source());
+            m->Declaration()->source);
 
         AddNote("see layout of struct:\n" + get_struct_layout_string(str),
-                str->Declaration()->source());
+                str->Declaration()->source);
 
         auto* prev_member_str = prev_member->Type()->As<sem::Struct>();
         AddNote("and layout of previous member struct:\n" +
                     get_struct_layout_string(prev_member_str),
-                prev_member_str->Declaration()->source());
+                prev_member_str->Declaration()->source);
         return false;
       }
     }
@@ -896,9 +894,9 @@
                   std::to_string(
                       utils::RoundUp(required_align, arr->Stride())) +
                   ")]] on the array type",
-              m->Declaration()->type()->source());
+              m->Declaration()->type->source);
           AddNote("see layout of struct:\n" + get_struct_layout_string(str),
-                  str->Declaration()->source());
+                  str->Declaration()->source);
           return false;
         }
       }
@@ -921,7 +919,7 @@
 bool Resolver::ValidateStorageClassLayout(const VariableInfo* info) {
   if (auto* str = info->type->UnwrapRef()->As<sem::Struct>()) {
     if (!ValidateStorageClassLayout(str, info->storage_class)) {
-      AddNote("see declaration of variable", info->declaration->source());
+      AddNote("see declaration of variable", info->declaration->source);
       return false;
     }
   }
@@ -930,34 +928,34 @@
 }
 
 bool Resolver::ValidateGlobalVariable(const VariableInfo* info) {
-  if (!ValidateNoDuplicateDecorations(info->declaration->decorations())) {
+  if (!ValidateNoDuplicateDecorations(info->declaration->decorations)) {
     return false;
   }
 
-  for (auto* deco : info->declaration->decorations()) {
-    if (info->declaration->is_const()) {
+  for (auto* deco : info->declaration->decorations) {
+    if (info->declaration->is_const) {
       if (auto* override_deco = deco->As<ast::OverrideDecoration>()) {
-        if (override_deco->HasValue()) {
-          uint32_t id = override_deco->value();
+        if (override_deco->has_value) {
+          uint32_t id = override_deco->value;
           auto itr = constant_ids_.find(id);
           if (itr != constant_ids_.end() && itr->second != info) {
-            AddError("pipeline constant IDs must be unique", deco->source());
+            AddError("pipeline constant IDs must be unique", deco->source);
             AddNote("a pipeline constant with an ID of " + std::to_string(id) +
                         " was previously declared "
                         "here:",
                     ast::GetDecoration<ast::OverrideDecoration>(
-                        itr->second->declaration->decorations())
-                        ->source());
+                        itr->second->declaration->decorations)
+                        ->source);
             return false;
           }
           if (id > 65535) {
             AddError("pipeline constant IDs must be between 0 and 65535",
-                     deco->source());
+                     deco->source);
             return false;
           }
         }
       } else {
-        AddError("decoration is not valid for constants", deco->source());
+        AddError("decoration is not valid for constants", deco->source);
         return false;
       }
     } else {
@@ -970,13 +968,13 @@
       if (!(deco->IsAnyOf<ast::BindingDecoration, ast::GroupDecoration,
                           ast::InternalDecoration>()) &&
           (!is_shader_io_decoration || !has_io_storage_class)) {
-        AddError("decoration is not valid for variables", deco->source());
+        AddError("decoration is not valid for variables", deco->source);
         return false;
       }
     }
   }
 
-  auto binding_point = info->declaration->binding_point();
+  auto binding_point = info->declaration->BindingPoint();
   switch (info->storage_class) {
     case ast::StorageClass::kUniform:
     case ast::StorageClass::kStorage:
@@ -988,7 +986,7 @@
         AddError(
             "resource variables require [[group]] and [[binding]] "
             "decorations",
-            info->declaration->source());
+            info->declaration->source);
         return false;
       }
       break;
@@ -1000,7 +998,7 @@
         AddError(
             "non-resource variables must not have [[group]] or [[binding]] "
             "decorations",
-            info->declaration->source());
+            info->declaration->source);
         return false;
       }
   }
@@ -1009,10 +1007,10 @@
   // The access mode always has a default, and except for variables in the
   // storage storage class, must not be written.
   if (info->storage_class != ast::StorageClass::kStorage &&
-      info->declaration->declared_access() != ast::Access::kUndefined) {
+      info->declaration->declared_access != ast::Access::kUndefined) {
     AddError(
         "only variables in <storage> storage class may declare an access mode",
-        info->declaration->source());
+        info->declaration->source);
     return false;
   }
 
@@ -1029,7 +1027,7 @@
         AddError(
             "variables declared in the <storage> storage class must be of a "
             "structure type",
-            info->declaration->source());
+            info->declaration->source);
         return false;
       }
 
@@ -1037,10 +1035,10 @@
         AddError(
             "structure used as a storage buffer must be declared with the "
             "[[block]] decoration",
-            str->Declaration()->source());
-        if (info->declaration->source().range.begin.line) {
+            str->Declaration()->source);
+        if (info->declaration->source.range.begin.line) {
           AddNote("structure used as storage buffer here",
-                  info->declaration->source());
+                  info->declaration->source);
         }
         return false;
       }
@@ -1056,7 +1054,7 @@
         AddError(
             "variables declared in the <uniform> storage class must be of a "
             "structure type",
-            info->declaration->source());
+            info->declaration->source);
         return false;
       }
 
@@ -1064,10 +1062,10 @@
         AddError(
             "structure used as a uniform buffer must be declared with the "
             "[[block]] decoration",
-            str->Declaration()->source());
-        if (info->declaration->source().range.begin.line) {
+            str->Declaration()->source);
+        if (info->declaration->source.range.begin.line) {
           AddNote("structure used as uniform buffer here",
-                  info->declaration->source());
+                  info->declaration->source);
         }
         return false;
       }
@@ -1078,8 +1076,8 @@
             AddError(
                 "structure containing a runtime sized array "
                 "cannot be used as a uniform buffer",
-                info->declaration->source());
-            AddNote("structure is declared here", str->Declaration()->source());
+                info->declaration->source);
+            AddNote("structure is declared here", str->Declaration()->source);
             return false;
           }
         }
@@ -1091,7 +1089,7 @@
       break;
   }
 
-  if (!info->declaration->is_const()) {
+  if (!info->declaration->is_const) {
     if (!ValidateAtomicVariable(info)) {
       return false;
     }
@@ -1107,8 +1105,8 @@
   auto sc = info->storage_class;
   auto access = info->access;
   auto* type = info->type->UnwrapRef();
-  auto source = info->declaration->type() ? info->declaration->type()->source()
-                                          : info->declaration->source();
+  auto source = info->declaration->type ? info->declaration->type->source
+                                        : info->declaration->source;
 
   if (type->Is<sem::Atomic>()) {
     if (sc != ast::StorageClass::kWorkgroup) {
@@ -1152,59 +1150,59 @@
   auto* var = info->declaration;
   auto* storage_type = info->type->UnwrapRef();
 
-  if (!var->is_const() && !IsStorable(storage_type)) {
+  if (!var->is_const && !IsStorable(storage_type)) {
     AddError(storage_type->FriendlyName(builder_->Symbols()) +
                  " cannot be used as the type of a var",
-             var->source());
+             var->source);
     return false;
   }
 
-  if (var->is_const() && info->kind != VariableKind::kParameter &&
+  if (var->is_const && info->kind != VariableKind::kParameter &&
       !(storage_type->IsConstructible() || storage_type->Is<sem::Pointer>())) {
     AddError(storage_type->FriendlyName(builder_->Symbols()) +
                  " cannot be used as the type of a let",
-             var->source());
+             var->source);
     return false;
   }
 
   if (auto* r = storage_type->As<sem::Array>()) {
     if (r->IsRuntimeSized()) {
       AddError("runtime arrays may only appear as the last member of a struct",
-               var->source());
+               var->source);
       return false;
     }
   }
 
   if (auto* r = storage_type->As<sem::MultisampledTexture>()) {
     if (r->dim() != ast::TextureDimension::k2d) {
-      AddError("only 2d multisampled textures are supported", var->source());
+      AddError("only 2d multisampled textures are supported", var->source);
       return false;
     }
 
     if (!r->type()->UnwrapRef()->is_numeric_scalar()) {
       AddError("texture_multisampled_2d<type>: type must be f32, i32 or u32",
-               var->source());
+               var->source);
       return false;
     }
   }
 
   if (storage_type->is_handle() &&
-      var->declared_storage_class() != ast::StorageClass::kNone) {
+      var->declared_storage_class != ast::StorageClass::kNone) {
     // https://gpuweb.github.io/gpuweb/wgsl/#module-scope-variables
     // If the store type is a texture type or a sampler type, then the
     // variable declaration must not have a storage class decoration. The
     // storage class will always be handle.
     AddError("variables of type '" + info->type_name +
                  "' must not have a storage class",
-             var->source());
+             var->source);
     return false;
   }
 
-  if (IsValidationEnabled(var->decorations(),
+  if (IsValidationEnabled(var->decorations,
                           ast::DisabledValidation::kIgnoreStorageClass) &&
-      (var->declared_storage_class() == ast::StorageClass::kInput ||
-       var->declared_storage_class() == ast::StorageClass::kOutput)) {
-    AddError("invalid use of input/output storage class", var->source());
+      (var->declared_storage_class == ast::StorageClass::kInput ||
+       var->declared_storage_class == ast::StorageClass::kOutput)) {
+    AddError("invalid use of input/output storage class", var->source);
     return false;
   }
   return true;
@@ -1216,25 +1214,24 @@
     return false;
   }
 
-  for (auto* deco : info->declaration->decorations()) {
+  for (auto* deco : info->declaration->decorations) {
     if (!func->IsEntryPoint() && !deco->Is<ast::InternalDecoration>()) {
       AddError(
           "decoration is not valid for non-entry point function parameters",
-          deco->source());
+          deco->source);
       return false;
     } else if (!deco->IsAnyOf<ast::BuiltinDecoration, ast::InvariantDecoration,
                               ast::LocationDecoration,
                               ast::InterpolateDecoration,
                               ast::InternalDecoration>() &&
                (IsValidationEnabled(
-                    info->declaration->decorations(),
+                    info->declaration->decorations,
                     ast::DisabledValidation::kEntryPointParameter) &&
                 IsValidationEnabled(
-                    info->declaration->decorations(),
+                    info->declaration->decorations,
                     ast::DisabledValidation::
                         kIgnoreConstructibleFunctionParameter))) {
-      AddError("decoration is not valid for function parameters",
-               deco->source());
+      AddError("decoration is not valid for function parameters", deco->source);
       return false;
     }
   }
@@ -1247,7 +1244,7 @@
       std::stringstream ss;
       ss << "function parameter of pointer type cannot be in '" << sc
          << "' storage class";
-      AddError(ss.str(), info->declaration->source());
+      AddError(ss.str(), info->declaration->source);
       return false;
     }
   }
@@ -1255,16 +1252,16 @@
   if (IsPlain(info->type)) {
     if (!info->type->IsConstructible() &&
         IsValidationEnabled(
-            info->declaration->decorations(),
+            info->declaration->decorations,
             ast::DisabledValidation::kIgnoreConstructibleFunctionParameter)) {
       AddError("store type of function parameter must be a constructible type",
-               info->declaration->source());
+               info->declaration->source);
       return false;
     }
   } else if (!info->type->IsAnyOf<sem::Texture, sem::Sampler, sem::Pointer>()) {
     AddError("store type of function parameter cannot be " +
                  info->type->FriendlyName(builder_->Symbols()),
-             info->declaration->source());
+             info->declaration->source);
     return false;
   }
 
@@ -1276,13 +1273,13 @@
                                          const bool is_input) {
   auto* type = storage_type->UnwrapRef();
   const auto stage = current_function_
-                         ? current_function_->declaration->pipeline_stage()
+                         ? current_function_->declaration->PipelineStage()
                          : ast::PipelineStage::kNone;
   std::stringstream stage_name;
   stage_name << stage;
   bool is_stage_mismatch = false;
   bool is_output = !is_input;
-  switch (deco->value()) {
+  switch (deco->builtin) {
     case ast::Builtin::kPosition:
       if (stage != ast::PipelineStage::kNone &&
           !((is_input && stage == ast::PipelineStage::kFragment) ||
@@ -1291,7 +1288,7 @@
       }
       if (!(type->is_float_vector() && type->As<sem::Vector>()->Width() == 4)) {
         AddError("store type of " + deco_to_str(deco) + " must be 'vec4<f32>'",
-                 deco->source());
+                 deco->source);
         return false;
       }
       break;
@@ -1306,7 +1303,7 @@
       if (!(type->is_unsigned_integer_vector() &&
             type->As<sem::Vector>()->Width() == 3)) {
         AddError("store type of " + deco_to_str(deco) + " must be 'vec3<u32>'",
-                 deco->source());
+                 deco->source);
         return false;
       }
       break;
@@ -1317,7 +1314,7 @@
       }
       if (!type->Is<sem::F32>()) {
         AddError("store type of " + deco_to_str(deco) + " must be 'f32'",
-                 deco->source());
+                 deco->source);
         return false;
       }
       break;
@@ -1328,7 +1325,7 @@
       }
       if (!type->Is<sem::Bool>()) {
         AddError("store type of " + deco_to_str(deco) + " must be 'bool'",
-                 deco->source());
+                 deco->source);
         return false;
       }
       break;
@@ -1339,7 +1336,7 @@
       }
       if (!type->Is<sem::U32>()) {
         AddError("store type of " + deco_to_str(deco) + " must be 'u32'",
-                 deco->source());
+                 deco->source);
         return false;
       }
       break;
@@ -1351,7 +1348,7 @@
       }
       if (!type->Is<sem::U32>()) {
         AddError("store type of " + deco_to_str(deco) + " must be 'u32'",
-                 deco->source());
+                 deco->source);
         return false;
       }
       break;
@@ -1362,7 +1359,7 @@
       }
       if (!type->Is<sem::U32>()) {
         AddError("store type of " + deco_to_str(deco) + " must be 'u32'",
-                 deco->source());
+                 deco->source);
         return false;
       }
       break;
@@ -1373,7 +1370,7 @@
       }
       if (!type->Is<sem::U32>()) {
         AddError("store type of " + deco_to_str(deco) + " must be 'u32'",
-                 deco->source());
+                 deco->source);
         return false;
       }
       break;
@@ -1385,7 +1382,7 @@
     AddError(deco_to_str(deco) + " cannot be used in " +
                  (is_input ? "input of " : "output of ") + stage_name.str() +
                  " pipeline stage",
-             deco->source());
+             deco->source);
     return false;
   }
 
@@ -1401,14 +1398,14 @@
     AddError(
         "store type of interpolate attribute must be floating point scalar or "
         "vector",
-        deco->source());
+        deco->source);
     return false;
   }
 
-  if (deco->type() == ast::InterpolationType::kFlat &&
-      deco->sampling() != ast::InterpolationSampling::kNone) {
+  if (deco->type == ast::InterpolationType::kFlat &&
+      deco->sampling != ast::InterpolationSampling::kNone) {
     AddError("flat interpolation attribute must not have a sampling parameter",
-             deco->source());
+             deco->source);
     return false;
   }
 
@@ -1417,34 +1414,34 @@
 
 bool Resolver::ValidateFunction(const ast::Function* func,
                                 const FunctionInfo* info) {
-  if (!ValidateNoDuplicateDefinition(func->symbol(), func->source(),
+  if (!ValidateNoDuplicateDefinition(func->symbol, func->source,
                                      /* check_global_scope_only */ true)) {
     return false;
   }
 
   auto workgroup_deco_count = 0;
-  for (auto* deco : func->decorations()) {
+  for (auto* deco : func->decorations) {
     if (deco->Is<ast::WorkgroupDecoration>()) {
       workgroup_deco_count++;
-      if (func->pipeline_stage() != ast::PipelineStage::kCompute) {
+      if (func->PipelineStage() != ast::PipelineStage::kCompute) {
         AddError(
             "the workgroup_size attribute is only valid for compute stages",
-            deco->source());
+            deco->source);
         return false;
       }
     } else if (!deco->IsAnyOf<ast::StageDecoration,
                               ast::InternalDecoration>()) {
-      AddError("decoration is not valid for functions", deco->source());
+      AddError("decoration is not valid for functions", deco->source);
       return false;
     }
   }
 
-  if (func->params().size() > 255) {
-    AddError("functions may declare at most 255 parameters", func->source());
+  if (func->params.size() > 255) {
+    AddError("functions may declare at most 255 parameters", func->source);
     return false;
   }
 
-  for (auto* param : func->params()) {
+  for (auto* param : func->params) {
     if (!ValidateFunctionParameter(func, variable_to_info_.at(param))) {
       return false;
     }
@@ -1453,42 +1450,42 @@
   if (!info->return_type->Is<sem::Void>()) {
     if (!info->return_type->IsConstructible()) {
       AddError("function return type must be a constructible type",
-               func->return_type()->source());
+               func->return_type->source);
       return false;
     }
 
-    if (func->body()) {
-      if (!func->get_last_statement() ||
-          !func->get_last_statement()->Is<ast::ReturnStatement>()) {
+    if (func->body) {
+      if (!func->body->Last() ||
+          !func->body->Last()->Is<ast::ReturnStatement>()) {
         AddError("non-void function must end with a return statement",
-                 func->source());
+                 func->source);
         return false;
       }
     } else if (IsValidationEnabled(
-                   func->decorations(),
+                   func->decorations,
                    ast::DisabledValidation::kFunctionHasNoBody)) {
       TINT_ICE(Resolver, diagnostics_)
-          << "Function " << builder_->Symbols().NameFor(func->symbol())
+          << "Function " << builder_->Symbols().NameFor(func->symbol)
           << " has no body";
     }
 
-    for (auto* deco : func->return_type_decorations()) {
+    for (auto* deco : func->return_type_decorations) {
       if (!func->IsEntryPoint()) {
         AddError(
             "decoration is not valid for non-entry point function return types",
-            deco->source());
+            deco->source);
         return false;
       }
       if (!deco->IsAnyOf<ast::BuiltinDecoration, ast::InternalDecoration,
                          ast::LocationDecoration, ast::InterpolateDecoration,
                          ast::InvariantDecoration>() &&
-          (IsValidationEnabled(info->declaration->decorations(),
+          (IsValidationEnabled(info->declaration->decorations,
                                ast::DisabledValidation::kEntryPointParameter) &&
-           IsValidationEnabled(info->declaration->decorations(),
+           IsValidationEnabled(info->declaration->decorations,
                                ast::DisabledValidation::
                                    kIgnoreConstructibleFunctionParameter))) {
         AddError("decoration is not valid for entry point return types",
-                 deco->source());
+                 deco->source);
         return false;
       }
     }
@@ -1529,21 +1526,21 @@
           auto is_invalid_compute_shader_decoration = false;
           if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
             if (pipeline_io_attribute) {
-              AddError("multiple entry point IO attributes", deco->source());
+              AddError("multiple entry point IO attributes", deco->source);
               AddNote(
                   "previously consumed " + deco_to_str(pipeline_io_attribute),
-                  pipeline_io_attribute->source());
+                  pipeline_io_attribute->source);
               return false;
             }
             pipeline_io_attribute = deco;
 
-            if (builtins.count(builtin->value())) {
+            if (builtins.count(builtin->builtin)) {
               AddError(
                   deco_to_str(builtin) +
                       " attribute appears multiple times as pipeline " +
                       (param_or_ret == ParamOrRetType::kParameter ? "input"
                                                                   : "output"),
-                  func->source());
+                  func->source);
               return false;
             }
 
@@ -1552,13 +1549,13 @@
                                                ParamOrRetType::kParameter)) {
               return false;
             }
-            builtins.emplace(builtin->value());
+            builtins.emplace(builtin->builtin);
           } else if (auto* location = deco->As<ast::LocationDecoration>()) {
             if (pipeline_io_attribute) {
-              AddError("multiple entry point IO attributes", deco->source());
+              AddError("multiple entry point IO attributes", deco->source);
               AddNote(
                   "previously consumed " + deco_to_str(pipeline_io_attribute),
-                  pipeline_io_attribute->source());
+                  pipeline_io_attribute->source);
               return false;
             }
             pipeline_io_attribute = deco;
@@ -1570,13 +1567,13 @@
             }
           } else if (auto* interpolate =
                          deco->As<ast::InterpolateDecoration>()) {
-            if (func->pipeline_stage() == ast::PipelineStage::kCompute) {
+            if (func->PipelineStage() == ast::PipelineStage::kCompute) {
               is_invalid_compute_shader_decoration = true;
             } else if (!ValidateInterpolateDecoration(interpolate, ty)) {
               return false;
             }
           } else if (auto* invariant = deco->As<ast::InvariantDecoration>()) {
-            if (func->pipeline_stage() == ast::PipelineStage::kCompute) {
+            if (func->PipelineStage() == ast::PipelineStage::kCompute) {
               is_invalid_compute_shader_decoration = true;
             }
             invariant_attribute = invariant;
@@ -1587,7 +1584,7 @@
                                                            : "output";
             AddError(
                 "decoration is not valid for compute shader " + input_or_output,
-                deco->source());
+                deco->source);
             return false;
           }
         }
@@ -1616,14 +1613,14 @@
             if (pipeline_io_attribute) {
               if (auto* builtin =
                       pipeline_io_attribute->As<ast::BuiltinDecoration>()) {
-                has_position = (builtin->value() == ast::Builtin::kPosition);
+                has_position = (builtin->builtin == ast::Builtin::kPosition);
               }
             }
             if (!has_position) {
               AddError(
                   "invariant attribute must only be applied to a position "
                   "builtin",
-                  invariant_attribute->source());
+                  invariant_attribute->source);
               return false;
             }
           }
@@ -1643,12 +1640,12 @@
     if (auto* str = ty->As<sem::Struct>()) {
       for (auto* member : str->Members()) {
         if (!validate_entry_point_decorations_inner(
-                member->Declaration()->decorations(), member->Type(),
-                member->Declaration()->source(), param_or_ret,
+                member->Declaration()->decorations, member->Type(),
+                member->Declaration()->source, param_or_ret,
                 /*is_struct_member*/ true)) {
           AddNote("while analysing entry point '" +
-                      builder_->Symbols().NameFor(func->symbol()) + "'",
-                  func->source());
+                      builder_->Symbols().NameFor(func->symbol) + "'",
+                  func->source);
           return false;
         }
       }
@@ -1659,8 +1656,8 @@
 
   for (auto* param : info->parameters) {
     if (!validate_entry_point_decorations(
-            param->declaration->decorations(), param->type,
-            param->declaration->source(), ParamOrRetType::kParameter)) {
+            param->declaration->decorations, param->type,
+            param->declaration->source, ParamOrRetType::kParameter)) {
       return false;
     }
   }
@@ -1672,21 +1669,21 @@
   locations.clear();
 
   if (!info->return_type->Is<sem::Void>()) {
-    if (!validate_entry_point_decorations(func->return_type_decorations(),
-                                          info->return_type, func->source(),
+    if (!validate_entry_point_decorations(func->return_type_decorations,
+                                          info->return_type, func->source,
                                           ParamOrRetType::kReturnType)) {
       return false;
     }
   }
 
-  if (func->pipeline_stage() == ast::PipelineStage::kVertex &&
+  if (func->PipelineStage() == ast::PipelineStage::kVertex &&
       builtins.count(ast::Builtin::kPosition) == 0) {
     // Check module-scope variables, as the SPIR-V sanitizer generates these.
     bool found = false;
     for (auto* var : info->referenced_module_vars) {
       if (auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(
-              var->declaration->decorations())) {
-        if (builtin->value() == ast::Builtin::kPosition) {
+              var->declaration->decorations)) {
+        if (builtin->builtin == ast::Builtin::kPosition) {
           found = true;
           break;
         }
@@ -1696,17 +1693,17 @@
       AddError(
           "a vertex shader must include the 'position' builtin in its return "
           "type",
-          func->source());
+          func->source);
       return false;
     }
   }
 
-  if (func->pipeline_stage() == ast::PipelineStage::kCompute) {
-    if (!ast::HasDecoration<ast::WorkgroupDecoration>(func->decorations())) {
+  if (func->PipelineStage() == ast::PipelineStage::kCompute) {
+    if (!ast::HasDecoration<ast::WorkgroupDecoration>(func->decorations)) {
       AddError(
           "a compute shader must include 'workgroup_size' in its "
           "attributes",
-          func->source());
+          func->source);
       return false;
     }
   }
@@ -1714,30 +1711,30 @@
   // Validate there are no resource variable binding collisions
   std::unordered_map<sem::BindingPoint, const ast::Variable*> binding_points;
   for (auto* var_info : info->referenced_module_vars) {
-    if (!var_info->declaration->binding_point()) {
+    if (!var_info->declaration->BindingPoint()) {
       continue;
     }
     auto bp = var_info->binding_point;
     auto res = binding_points.emplace(bp, var_info->declaration);
     if (!res.second &&
-        IsValidationEnabled(var_info->declaration->decorations(),
+        IsValidationEnabled(var_info->declaration->decorations,
                             ast::DisabledValidation::kBindingPointCollision) &&
-        IsValidationEnabled(res.first->second->decorations(),
+        IsValidationEnabled(res.first->second->decorations,
                             ast::DisabledValidation::kBindingPointCollision)) {
       // https://gpuweb.github.io/gpuweb/wgsl/#resource-interface
       // Bindings must not alias within a shader stage: two different
       // variables in the resource interface of a given shader must not have
       // the same group and binding values, when considered as a pair of
       // values.
-      auto func_name = builder_->Symbols().NameFor(info->declaration->symbol());
+      auto func_name = builder_->Symbols().NameFor(info->declaration->symbol);
       AddError("entry point '" + func_name +
                    "' references multiple variables that use the "
                    "same resource binding [[group(" +
                    std::to_string(bp.group) + "), binding(" +
                    std::to_string(bp.binding) + ")]]",
-               var_info->declaration->source());
+               var_info->declaration->source);
       AddNote("first resource binding usage declared here",
-              res.first->second->source());
+              res.first->second->source);
       return false;
     }
   }
@@ -1757,14 +1754,14 @@
   variable_stack_.push_scope();
   uint32_t parameter_index = 0;
   std::unordered_map<Symbol, Source> parameter_names;
-  for (auto* param : func->params()) {
+  for (auto* param : func->params) {
     Mark(param);
 
     {  // Check the parameter name is unique for the function
-      auto emplaced = parameter_names.emplace(param->symbol(), param->source());
+      auto emplaced = parameter_names.emplace(param->symbol, param->source);
       if (!emplaced.second) {
-        auto name = builder_->Symbols().NameFor(param->symbol());
-        AddError("redefinition of parameter '" + name + "'", param->source());
+        auto name = builder_->Symbols().NameFor(param->symbol);
+        AddError("redefinition of parameter '" + name + "'", param->source);
         AddNote("previous definition is here", emplaced.first->second);
         return false;
       }
@@ -1776,26 +1773,26 @@
       return false;
     }
 
-    for (auto* deco : param->decorations()) {
+    for (auto* deco : param->decorations) {
       Mark(deco);
     }
-    if (!ValidateNoDuplicateDecorations(param->decorations())) {
+    if (!ValidateNoDuplicateDecorations(param->decorations)) {
       return false;
     }
 
-    variable_stack_.set(param->symbol(), param_info);
+    variable_stack_.set(param->symbol, param_info);
     info->parameters.emplace_back(param_info);
 
-    if (!ApplyStorageClassUsageToType(param->declared_storage_class(),
-                                      param_info->type, param->source())) {
+    if (!ApplyStorageClassUsageToType(param->declared_storage_class,
+                                      param_info->type, param->source)) {
       AddNote("while instantiating parameter " +
-                  builder_->Symbols().NameFor(param->symbol()),
-              param->source());
+                  builder_->Symbols().NameFor(param->symbol),
+              param->source);
       return false;
     }
 
     if (auto* str = param_info->type->As<sem::Struct>()) {
-      switch (func->pipeline_stage()) {
+      switch (func->PipelineStage()) {
         case ast::PipelineStage::kVertex:
           str->AddUsage(sem::PipelineStageUsage::kVertexInput);
           break;
@@ -1811,7 +1808,7 @@
     }
   }
 
-  if (auto* ty = func->return_type()) {
+  if (auto* ty = func->return_type) {
     info->return_type = Type(ty);
     info->return_type_name = ty->FriendlyName(builder_->Symbols());
     if (!info->return_type) {
@@ -1825,14 +1822,14 @@
 
   if (auto* str = info->return_type->As<sem::Struct>()) {
     if (!ApplyStorageClassUsageToType(ast::StorageClass::kNone, str,
-                                      func->source())) {
+                                      func->source)) {
       AddNote("while instantiating return type for " +
-                  builder_->Symbols().NameFor(func->symbol()),
-              func->source());
+                  builder_->Symbols().NameFor(func->symbol),
+              func->source);
       return false;
     }
 
-    switch (func->pipeline_stage()) {
+    switch (func->PipelineStage()) {
       case ast::PipelineStage::kVertex:
         str->AddUsage(sem::PipelineStageUsage::kVertexOutput);
         break;
@@ -1847,32 +1844,32 @@
     }
   }
 
-  if (func->body()) {
-    Mark(func->body());
+  if (func->body) {
+    Mark(func->body);
     if (current_compound_statement_) {
       TINT_ICE(Resolver, diagnostics_)
           << "Resolver::Function() called with a current compound statement";
       return false;
     }
     auto* sem_block = builder_->create<sem::FunctionBlockStatement>(func);
-    builder_->Sem().Add(func->body(), sem_block);
-    if (!Scope(sem_block, [&] { return Statements(func->body()->list()); })) {
+    builder_->Sem().Add(func->body, sem_block);
+    if (!Scope(sem_block, [&] { return Statements(func->body->statements); })) {
       return false;
     }
   }
   variable_stack_.pop_scope();
 
-  for (auto* deco : func->decorations()) {
+  for (auto* deco : func->decorations) {
     Mark(deco);
   }
-  if (!ValidateNoDuplicateDecorations(func->decorations())) {
+  if (!ValidateNoDuplicateDecorations(func->decorations)) {
     return false;
   }
 
-  for (auto* deco : func->return_type_decorations()) {
+  for (auto* deco : func->return_type_decorations) {
     Mark(deco);
   }
-  if (!ValidateNoDuplicateDecorations(func->return_type_decorations())) {
+  if (!ValidateNoDuplicateDecorations(func->return_type_decorations)) {
     return false;
   }
 
@@ -1883,8 +1880,8 @@
   }
 
   if (auto* workgroup =
-          ast::GetDecoration<ast::WorkgroupDecoration>(func->decorations())) {
-    auto values = workgroup->values();
+          ast::GetDecoration<ast::WorkgroupDecoration>(func->decorations)) {
+    auto values = workgroup->Values();
     auto any_i32 = false;
     auto any_u32 = false;
     for (int i = 0; i < 3; i++) {
@@ -1913,33 +1910,33 @@
       bool is_i32 = ty->UnwrapRef()->Is<sem::I32>();
       bool is_u32 = ty->UnwrapRef()->Is<sem::U32>();
       if (!is_i32 && !is_u32) {
-        AddError(kErrBadType, expr->source());
+        AddError(kErrBadType, expr->source);
         return false;
       }
 
       any_i32 = any_i32 || is_i32;
       any_u32 = any_u32 || is_u32;
       if (any_i32 && any_u32) {
-        AddError(kErrInconsistentType, expr->source());
+        AddError(kErrInconsistentType, expr->source);
         return false;
       }
 
       if (auto* ident = expr->As<ast::IdentifierExpression>()) {
         // We have an identifier of a module-scope constant.
         VariableInfo* var = nullptr;
-        if (!variable_stack_.get(ident->symbol(), &var) ||
-            !(var->declaration->is_const())) {
-          AddError(kErrBadType, expr->source());
+        if (!variable_stack_.get(ident->symbol, &var) ||
+            !(var->declaration->is_const)) {
+          AddError(kErrBadType, expr->source);
           return false;
         }
 
         // Capture the constant if an [[override]] attribute is present.
         if (ast::HasDecoration<ast::OverrideDecoration>(
-                var->declaration->decorations())) {
+                var->declaration->decorations)) {
           info->workgroup_size[i].overridable_const = var->declaration;
         }
 
-        expr = var->declaration->constructor();
+        expr = var->declaration->constructor;
         if (!expr) {
           // No constructor means this value must be overriden by the user.
           info->workgroup_size[i].value = 0;
@@ -1949,7 +1946,7 @@
         AddError(
             "workgroup_size argument must be either a literal or a "
             "module-scope constant",
-            values[i]->source());
+            values[i]->source);
         return false;
       }
 
@@ -1962,7 +1959,7 @@
       // Validate and set the default value for this dimension.
       if (is_i32 ? val.Elements()[0].i32 < 1 : val.Elements()[0].u32 < 1) {
         AddError("workgroup_size argument must be at least 1",
-                 values[i]->source());
+                 values[i]->source);
         return false;
       }
 
@@ -1979,7 +1976,7 @@
   // Register the function information _after_ processing the statements. This
   // allows us to catch a function calling itself when determining the call
   // information as this function doesn't exist until it's finished.
-  symbol_to_function_[func->symbol()] = info;
+  symbol_to_function_[func->symbol] = info;
   function_to_info_.emplace(func, info);
 
   return true;
@@ -2003,16 +2000,16 @@
   bool unreachable = false;
   for (auto* stmt : stmts) {
     if (unreachable) {
-      AddError("code is unreachable", stmt->source());
+      AddError("code is unreachable", stmt->source);
       return false;
     }
 
     auto* nested_stmt = stmt;
     while (auto* block = nested_stmt->As<ast::BlockStatement>()) {
-      if (block->empty()) {
+      if (block->Empty()) {
         break;
       }
-      nested_stmt = block->statements().back();
+      nested_stmt = block->statements.back();
     }
     if (nested_stmt->IsAnyOf<ast::ReturnStatement, ast::BreakStatement,
                              ast::ContinueStatement, ast::DiscardStatement>()) {
@@ -2025,7 +2022,7 @@
 bool Resolver::Statement(ast::Statement* stmt) {
   if (stmt->Is<ast::CaseStatement>()) {
     AddError("case statement can only be used inside a switch statement",
-             stmt->source());
+             stmt->source);
     return false;
   }
   if (stmt->Is<ast::ElseStatement>()) {
@@ -2066,14 +2063,14 @@
     if (!sem_statement->FindFirstParent<sem::LoopBlockStatement>() &&
         !sem_statement->FindFirstParent<sem::SwitchCaseBlockStatement>()) {
       AddError("break statement must be in a loop or switch case",
-               stmt->source());
+               stmt->source);
       return false;
     }
     return true;
   }
   if (auto* c = stmt->As<ast::CallStatement>()) {
-    Mark(c->expr());
-    if (!Expression(c->expr())) {
+    Mark(c->expr);
+    if (!Expression(c->expr)) {
       return false;
     }
     if (!ValidateCallStatement(c)) {
@@ -2093,11 +2090,11 @@
         }
       } else {
         AddError("continuing blocks must not contain a continue statement",
-                 stmt->source());
+                 stmt->source);
         return false;
       }
     } else {
-      AddError("continue statement must be in a loop", stmt->source());
+      AddError("continue statement must be in a loop", stmt->source);
       return false;
     }
 
@@ -2108,10 +2105,9 @@
             sem_statement
                 ->FindFirstParent<sem::LoopContinuingBlockStatement>()) {
       AddError("continuing blocks must not contain a discard statement",
-               stmt->source());
+               stmt->source);
       if (continuing != sem_statement->Parent()) {
-        AddNote("see continuing block here",
-                continuing->Declaration()->source());
+        AddNote("see continuing block here", continuing->Declaration()->source);
       }
       return false;
     }
@@ -2129,20 +2125,20 @@
 
   AddError("unknown statement type for type determination: " +
                std::string(stmt->TypeInfo().name),
-           stmt->source());
+           stmt->source);
   return false;
 }
 
 bool Resolver::CaseStatement(ast::CaseStatement* stmt) {
   auto* sem = builder_->create<sem::SwitchCaseBlockStatement>(
-      stmt->body(), current_compound_statement_);
+      stmt->body, current_compound_statement_);
   builder_->Sem().Add(stmt, sem);
-  builder_->Sem().Add(stmt->body(), sem);
-  Mark(stmt->body());
-  for (auto* sel : stmt->selectors()) {
+  builder_->Sem().Add(stmt->body, sem);
+  Mark(stmt->body);
+  for (auto* sel : stmt->selectors) {
     Mark(sel);
   }
-  return Scope(sem, [&] { return Statements(stmt->body()->list()); });
+  return Scope(sem, [&] { return Statements(stmt->body->statements); });
 }
 
 bool Resolver::IfStatement(ast::IfStatement* stmt) {
@@ -2150,28 +2146,28 @@
       builder_->create<sem::IfStatement>(stmt, current_compound_statement_);
   builder_->Sem().Add(stmt, sem);
   return Scope(sem, [&] {
-    Mark(stmt->condition());
-    if (!Expression(stmt->condition())) {
+    Mark(stmt->condition);
+    if (!Expression(stmt->condition)) {
       return false;
     }
 
-    auto* cond_type = TypeOf(stmt->condition())->UnwrapRef();
+    auto* cond_type = TypeOf(stmt->condition)->UnwrapRef();
     if (!cond_type->Is<sem::Bool>()) {
       AddError("if statement condition must be bool, got " +
                    cond_type->FriendlyName(builder_->Symbols()),
-               stmt->condition()->source());
+               stmt->condition->source);
       return false;
     }
 
-    Mark(stmt->body());
+    Mark(stmt->body);
     auto* body = builder_->create<sem::BlockStatement>(
-        stmt->body(), current_compound_statement_);
-    builder_->Sem().Add(stmt->body(), body);
-    if (!Scope(body, [&] { return Statements(stmt->body()->list()); })) {
+        stmt->body, current_compound_statement_);
+    builder_->Sem().Add(stmt->body, body);
+    if (!Scope(body, [&] { return Statements(stmt->body->statements); })) {
       return false;
     }
 
-    for (auto* else_stmt : stmt->else_statements()) {
+    for (auto* else_stmt : stmt->else_statements) {
       Mark(else_stmt);
       if (!ElseStatement(else_stmt)) {
         return false;
@@ -2186,7 +2182,7 @@
       builder_->create<sem::ElseStatement>(stmt, current_compound_statement_);
   builder_->Sem().Add(stmt, sem);
   return Scope(sem, [&] {
-    if (auto* cond = stmt->condition()) {
+    if (auto* cond = stmt->condition) {
       Mark(cond);
       if (!Expression(cond)) {
         return false;
@@ -2196,16 +2192,16 @@
       if (!else_cond_type->Is<sem::Bool>()) {
         AddError("else statement condition must be bool, got " +
                      else_cond_type->FriendlyName(builder_->Symbols()),
-                 cond->source());
+                 cond->source);
         return false;
       }
     }
 
-    Mark(stmt->body());
+    Mark(stmt->body);
     auto* body = builder_->create<sem::BlockStatement>(
-        stmt->body(), current_compound_statement_);
-    builder_->Sem().Add(stmt->body(), body);
-    return Scope(body, [&] { return Statements(stmt->body()->list()); });
+        stmt->body, current_compound_statement_);
+    builder_->Sem().Add(stmt->body, body);
+    return Scope(body, [&] { return Statements(stmt->body->statements); });
   });
 }
 
@@ -2213,7 +2209,7 @@
   auto* sem = builder_->create<sem::BlockStatement>(
       stmt->As<ast::BlockStatement>(), current_compound_statement_);
   builder_->Sem().Add(stmt, sem);
-  return Scope(sem, [&] { return Statements(stmt->list()); });
+  return Scope(sem, [&] { return Statements(stmt->statements); });
 }
 
 bool Resolver::LoopStatement(ast::LoopStatement* stmt) {
@@ -2221,25 +2217,27 @@
       builder_->create<sem::LoopStatement>(stmt, current_compound_statement_);
   builder_->Sem().Add(stmt, sem);
   return Scope(sem, [&] {
-    Mark(stmt->body());
+    Mark(stmt->body);
 
     auto* body = builder_->create<sem::LoopBlockStatement>(
-        stmt->body(), current_compound_statement_);
-    builder_->Sem().Add(stmt->body(), body);
+        stmt->body, current_compound_statement_);
+    builder_->Sem().Add(stmt->body, body);
     return Scope(body, [&] {
-      if (!Statements(stmt->body()->list())) {
+      if (!Statements(stmt->body->statements)) {
         return false;
       }
-      if (stmt->continuing()) {  // has_continuing() also checks for empty()
-        Mark(stmt->continuing());
-      }
-      if (stmt->has_continuing()) {
-        auto* continuing = builder_->create<sem::LoopContinuingBlockStatement>(
-            stmt->continuing(), current_compound_statement_);
-        builder_->Sem().Add(stmt->continuing(), continuing);
-        if (!Scope(continuing,
-                   [&] { return Statements(stmt->continuing()->list()); })) {
-          return false;
+      if (stmt->continuing) {
+        Mark(stmt->continuing);
+        if (!stmt->continuing->Empty()) {
+          auto* continuing =
+              builder_->create<sem::LoopContinuingBlockStatement>(
+                  stmt->continuing, current_compound_statement_);
+          builder_->Sem().Add(stmt->continuing, continuing);
+          if (!Scope(continuing, [&] {
+                return Statements(stmt->continuing->statements);
+              })) {
+            return false;
+          }
         }
       }
       return true;
@@ -2252,14 +2250,14 @@
       stmt, current_compound_statement_);
   builder_->Sem().Add(stmt, sem);
   return Scope(sem, [&] {
-    if (auto* initializer = stmt->initializer()) {
+    if (auto* initializer = stmt->initializer) {
       Mark(initializer);
       if (!Statement(initializer)) {
         return false;
       }
     }
 
-    if (auto* condition = stmt->condition()) {
+    if (auto* condition = stmt->condition) {
       Mark(condition);
       if (!Expression(condition)) {
         return false;
@@ -2268,24 +2266,24 @@
       if (!TypeOf(condition)->UnwrapRef()->Is<sem::Bool>()) {
         AddError(
             "for-loop condition must be bool, got " + TypeNameOf(condition),
-            condition->source());
+            condition->source);
         return false;
       }
     }
 
-    if (auto* continuing = stmt->continuing()) {
+    if (auto* continuing = stmt->continuing) {
       Mark(continuing);
       if (!Statement(continuing)) {
         return false;
       }
     }
 
-    Mark(stmt->body());
+    Mark(stmt->body);
 
     auto* body = builder_->create<sem::LoopBlockStatement>(
-        stmt->body(), current_compound_statement_);
-    builder_->Sem().Add(stmt->body(), body);
-    return Scope(body, [&] { return Statements(stmt->body()->statements()); });
+        stmt->body, current_compound_statement_);
+    builder_->Sem().Add(stmt->body, body);
+    return Scope(body, [&] { return Statements(stmt->body->statements); });
   });
 }
 
@@ -2306,25 +2304,25 @@
     out.emplace_back(expr);
 
     if (auto* array = expr->As<ast::ArrayAccessorExpression>()) {
-      add(array->array());
-      add(array->idx_expr());
+      add(array->array);
+      add(array->index);
     } else if (auto* bin_op = expr->As<ast::BinaryExpression>()) {
-      add(bin_op->lhs());
-      add(bin_op->rhs());
+      add(bin_op->lhs);
+      add(bin_op->rhs);
     } else if (auto* bitcast = expr->As<ast::BitcastExpression>()) {
-      add(bitcast->expr());
+      add(bitcast->expr);
     } else if (auto* call = expr->As<ast::CallExpression>()) {
-      for (auto* arg : call->args()) {
+      for (auto* arg : call->args) {
         add(arg);
       }
     } else if (auto* type_ctor = expr->As<ast::TypeConstructorExpression>()) {
-      for (auto* value : type_ctor->values()) {
+      for (auto* value : type_ctor->values) {
         add(value);
       }
     } else if (auto* member = expr->As<ast::MemberAccessorExpression>()) {
-      add(member->structure());
+      add(member->structure);
     } else if (auto* unary = expr->As<ast::UnaryOpExpression>()) {
-      add(unary->expr());
+      add(unary->expr);
     } else if (expr->IsAnyOf<ast::ScalarConstructorExpression,
                              ast::IdentifierExpression>()) {
       // Leaf expression
@@ -2376,8 +2374,8 @@
 }
 
 bool Resolver::ArrayAccessor(ast::ArrayAccessorExpression* expr) {
-  auto* idx = expr->idx_expr();
-  auto* res = TypeOf(expr->array());
+  auto* idx = expr->index;
+  auto* res = TypeOf(expr->array);
   auto* parent_type = res->UnwrapRef();
   const sem::Type* ret = nullptr;
   if (auto* arr = parent_type->As<sem::Array>()) {
@@ -2387,15 +2385,15 @@
   } else if (auto* mat = parent_type->As<sem::Matrix>()) {
     ret = builder_->create<sem::Vector>(mat->type(), mat->rows());
   } else {
-    AddError("cannot index type '" + TypeNameOf(expr->array()) + "'",
-             expr->source());
+    AddError("cannot index type '" + TypeNameOf(expr->array) + "'",
+             expr->source);
     return false;
   }
 
   if (!TypeOf(idx)->UnwrapRef()->IsAnyOf<sem::I32, sem::U32>()) {
     AddError("index must be of type 'i32' or 'u32', found: '" +
                  TypeNameOf(idx) + "'",
-             idx->source());
+             idx->source);
     return false;
   }
 
@@ -2404,9 +2402,9 @@
       // TODO(bclayton): expand this to allow any const_expr expression
       // https://github.com/gpuweb/gpuweb/issues/1272
       auto* scalar = idx->As<ast::ScalarConstructorExpression>();
-      if (!scalar || !scalar->literal()->As<ast::IntLiteral>()) {
+      if (!scalar || !scalar->literal->As<ast::IntLiteral>()) {
         AddError("index must be signed or unsigned integer literal",
-                 idx->source());
+                 idx->source);
         return false;
       }
     }
@@ -2423,22 +2421,22 @@
 }
 
 bool Resolver::Bitcast(ast::BitcastExpression* expr) {
-  auto* ty = Type(expr->type());
+  auto* ty = Type(expr->type);
   if (!ty) {
     return false;
   }
   if (ty->Is<sem::Pointer>()) {
-    AddError("cannot cast to a pointer", expr->source());
+    AddError("cannot cast to a pointer", expr->source);
     return false;
   }
-  SetExprInfo(expr, ty, expr->type()->FriendlyName(builder_->Symbols()));
+  SetExprInfo(expr, ty, expr->type->FriendlyName(builder_->Symbols()));
   return true;
 }
 
 bool Resolver::Call(ast::CallExpression* call) {
-  Mark(call->func());
-  auto* ident = call->func();
-  auto name = builder_->Symbols().NameFor(ident->symbol());
+  Mark(call->func);
+  auto* ident = call->func;
+  auto name = builder_->Symbols().NameFor(ident->symbol);
 
   auto intrinsic_type = sem::ParseIntrinsicType(name);
   if (intrinsic_type != IntrinsicType::kNone) {
@@ -2460,7 +2458,7 @@
     if (current_statement_) {
       if (auto* call_stmt =
               As<ast::CallStatement>(current_statement_->Declaration())) {
-        if (call_stmt->expr() == call) {
+        if (call_stmt->expr == call) {
           is_call_statement = true;
         }
       }
@@ -2469,15 +2467,15 @@
       // https://gpuweb.github.io/gpuweb/wgsl/#function-call-expr
       // If the called function does not return a value, a function call
       // statement should be used instead.
-      auto* ident = call->func();
-      auto name = builder_->Symbols().NameFor(ident->symbol());
+      auto* ident = call->func;
+      auto name = builder_->Symbols().NameFor(ident->symbol);
       // A function call is made to either a user declared function or an
       // intrinsic. function_calls_ only maps CallExpression to user declared
       // functions
       bool is_function = function_calls_.count(call) != 0;
       AddError((is_function ? "function" : "intrinsic") + std::string(" '") +
                    name + "' does not return a value",
-               call->source());
+               call->source);
       return false;
     }
   }
@@ -2486,7 +2484,7 @@
 }
 
 bool Resolver::ValidateCallStatement(ast::CallStatement* stmt) {
-  const sem::Type* return_type = TypeOf(stmt->expr());
+  const sem::Type* return_type = TypeOf(stmt->expr);
   if (!return_type->Is<sem::Void>()) {
     // https://gpuweb.github.io/gpuweb/wgsl/#function-call-statement
     // A function call statement executes a function call where the called
@@ -2497,7 +2495,7 @@
     AddError(
         "result of called function was not used. If this was intentional wrap "
         "the function call in ignore()",
-        stmt->source());
+        stmt->source);
     return false;
   }
   return true;
@@ -2506,19 +2504,19 @@
 bool Resolver::IntrinsicCall(ast::CallExpression* call,
                              sem::IntrinsicType intrinsic_type) {
   std::vector<const sem::Type*> arg_tys;
-  arg_tys.reserve(call->args().size());
-  for (auto* expr : call->args()) {
+  arg_tys.reserve(call->args.size());
+  for (auto* expr : call->args) {
     arg_tys.emplace_back(TypeOf(expr));
   }
 
   auto* result =
-      intrinsic_table_->Lookup(intrinsic_type, arg_tys, call->source());
+      intrinsic_table_->Lookup(intrinsic_type, arg_tys, call->source);
   if (!result) {
     return false;
   }
 
   if (result->IsDeprecated()) {
-    AddWarning("use of deprecated intrinsic", call->source());
+    AddWarning("use of deprecated intrinsic", call->source);
   }
 
   auto* out = builder_->create<sem::Call>(call, result, current_statement_);
@@ -2547,13 +2545,13 @@
   auto& signature = intrinsic->Signature();
   auto index = signature.IndexOf(sem::ParameterUsage::kOffset);
   if (index > -1) {
-    auto* param = ast_call->args()[index];
+    auto* param = ast_call->args[index];
     if (param->Is<ast::TypeConstructorExpression>()) {
       auto values = ConstantValueOf(param);
       if (!values.IsValid()) {
         AddError(
             "'" + func_name + "' offset parameter must be a const_expression",
-            param->source());
+            param->source);
         return false;
       }
       if (!values.Type()->Is<sem::Vector>() ||
@@ -2569,14 +2567,14 @@
                        "' must be at least -8 and at most 7. "
                        "found: '" +
                        std::to_string(offset_value) + "'",
-                   param->source());
+                   param->source);
           return false;
         }
       }
     } else {
       AddError(
           "'" + func_name + "' offset parameter must be a const_expression",
-          param->source());
+          param->source);
       return false;
     }
   }
@@ -2584,18 +2582,18 @@
 }
 
 bool Resolver::FunctionCall(const ast::CallExpression* call) {
-  auto* ident = call->func();
-  auto name = builder_->Symbols().NameFor(ident->symbol());
+  auto* ident = call->func;
+  auto name = builder_->Symbols().NameFor(ident->symbol);
 
-  auto callee_func_it = symbol_to_function_.find(ident->symbol());
+  auto callee_func_it = symbol_to_function_.find(ident->symbol);
   if (callee_func_it == symbol_to_function_.end()) {
     if (current_function_ &&
-        current_function_->declaration->symbol() == ident->symbol()) {
+        current_function_->declaration->symbol == ident->symbol) {
       AddError("recursion is not permitted. '" + name +
                    "' attempted to call itself.",
-               call->source());
+               call->source);
     } else {
-      AddError("unable to find called function: " + name, call->source());
+      AddError("unable to find called function: " + name, call->source);
     }
     return false;
   }
@@ -2630,30 +2628,30 @@
 
 bool Resolver::ValidateFunctionCall(const ast::CallExpression* call,
                                     const FunctionInfo* target) {
-  auto* ident = call->func();
-  auto name = builder_->Symbols().NameFor(ident->symbol());
+  auto* ident = call->func;
+  auto name = builder_->Symbols().NameFor(ident->symbol);
 
   if (target->declaration->IsEntryPoint()) {
     // https://www.w3.org/TR/WGSL/#function-restriction
     // An entry point must never be the target of a function call.
     AddError("entry point functions cannot be the target of a function call",
-             call->source());
+             call->source);
     return false;
   }
 
-  if (call->args().size() != target->parameters.size()) {
-    bool more = call->args().size() > target->parameters.size();
+  if (call->args.size() != target->parameters.size()) {
+    bool more = call->args.size() > target->parameters.size();
     AddError("too " + (more ? std::string("many") : std::string("few")) +
                  " arguments in call to '" + name + "', expected " +
                  std::to_string(target->parameters.size()) + ", got " +
-                 std::to_string(call->args().size()),
-             call->source());
+                 std::to_string(call->args.size()),
+             call->source);
     return false;
   }
 
-  for (size_t i = 0; i < call->args().size(); ++i) {
+  for (size_t i = 0; i < call->args.size(); ++i) {
     const VariableInfo* param = target->parameters[i];
-    const ast::Expression* arg_expr = call->args()[i];
+    const ast::Expression* arg_expr = call->args[i];
     auto* arg_type = TypeOf(arg_expr)->UnwrapRef();
 
     if (param->type != arg_type) {
@@ -2661,15 +2659,15 @@
                    " in call to '" + name + "', expected '" +
                    param->type->FriendlyName(builder_->Symbols()) + "', got '" +
                    arg_type->FriendlyName(builder_->Symbols()) + "'",
-               arg_expr->source());
+               arg_expr->source);
       return false;
     }
 
-    if (param->declaration->type()->Is<ast::Pointer>()) {
+    if (param->declaration->type->Is<ast::Pointer>()) {
       auto is_valid = false;
       if (auto* ident_expr = arg_expr->As<ast::IdentifierExpression>()) {
         VariableInfo* var;
-        if (!variable_stack_.get(ident_expr->symbol(), &var)) {
+        if (!variable_stack_.get(ident_expr->symbol, &var)) {
           TINT_ICE(Resolver, diagnostics_) << "failed to resolve identifier";
           return false;
         }
@@ -2677,16 +2675,16 @@
           is_valid = true;
         }
       } else if (auto* unary = arg_expr->As<ast::UnaryOpExpression>()) {
-        if (unary->op() == ast::UnaryOp::kAddressOf) {
+        if (unary->op == ast::UnaryOp::kAddressOf) {
           if (auto* ident_unary =
-                  unary->expr()->As<ast::IdentifierExpression>()) {
+                  unary->expr->As<ast::IdentifierExpression>()) {
             VariableInfo* var;
-            if (!variable_stack_.get(ident_unary->symbol(), &var)) {
+            if (!variable_stack_.get(ident_unary->symbol, &var)) {
               TINT_ICE(Resolver, diagnostics_)
                   << "failed to resolve identifier";
               return false;
             }
-            if (var->declaration->is_const()) {
+            if (var->declaration->is_const) {
               TINT_ICE(Resolver, diagnostics_)
                   << "Resolver::FunctionCall() encountered an address-of "
                      "expression of a constant identifier expression";
@@ -2699,12 +2697,12 @@
 
       if (!is_valid &&
           IsValidationEnabled(
-              param->declaration->decorations(),
+              param->declaration->decorations,
               ast::DisabledValidation::kIgnoreInvalidPointerArgument)) {
         AddError(
             "expected an address-of expression of a variable identifier "
             "expression or a function parameter",
-            arg_expr->source());
+            arg_expr->source);
         return false;
       }
     }
@@ -2714,12 +2712,12 @@
 
 bool Resolver::Constructor(ast::ConstructorExpression* expr) {
   if (auto* type_ctor = expr->As<ast::TypeConstructorExpression>()) {
-    auto* type = Type(type_ctor->type());
+    auto* type = Type(type_ctor->type);
     if (!type) {
       return false;
     }
 
-    auto type_name = type_ctor->type()->FriendlyName(builder_->Symbols());
+    auto type_name = type_ctor->type->FriendlyName(builder_->Symbols());
 
     // Now that the argument types have been determined, make sure that they
     // obey the constructor type rules laid out in
@@ -2736,7 +2734,7 @@
     } else if (auto* struct_type = type->As<sem::Struct>()) {
       ok = ValidateStructureConstructor(type_ctor, struct_type);
     } else {
-      AddError("type is not constructible", type_ctor->source());
+      AddError("type is not constructible", type_ctor->source);
       return false;
     }
     if (!ok) {
@@ -2747,8 +2745,8 @@
   }
 
   if (auto* scalar_ctor = expr->As<ast::ScalarConstructorExpression>()) {
-    Mark(scalar_ctor->literal());
-    auto* type = TypeOf(scalar_ctor->literal());
+    Mark(scalar_ctor->literal);
+    auto* type = TypeOf(scalar_ctor->literal);
     if (!type) {
       return false;
     }
@@ -2764,30 +2762,29 @@
     const ast::TypeConstructorExpression* ctor,
     const sem::Struct* struct_type) {
   if (!struct_type->IsConstructible()) {
-    AddError("struct constructor has non-constructible type", ctor->source());
+    AddError("struct constructor has non-constructible type", ctor->source);
     return false;
   }
 
-  if (ctor->values().size() > 0) {
-    if (ctor->values().size() != struct_type->Members().size()) {
-      std::string fm = ctor->values().size() < struct_type->Members().size()
-                           ? "few"
-                           : "many";
+  if (ctor->values.size() > 0) {
+    if (ctor->values.size() != struct_type->Members().size()) {
+      std::string fm =
+          ctor->values.size() < struct_type->Members().size() ? "few" : "many";
       AddError("struct constructor has too " + fm + " inputs: expected " +
                    std::to_string(struct_type->Members().size()) + ", found " +
-                   std::to_string(ctor->values().size()),
-               ctor->source());
+                   std::to_string(ctor->values.size()),
+               ctor->source);
       return false;
     }
     for (auto* member : struct_type->Members()) {
-      auto* value = ctor->values()[member->Index()];
+      auto* value = ctor->values[member->Index()];
       if (member->Type() != TypeOf(value)->UnwrapRef()) {
         AddError(
             "type in struct constructor does not match struct member type: "
             "expected '" +
                 member->Type()->FriendlyName(builder_->Symbols()) +
                 "', found '" + TypeNameOf(value) + "'",
-            value->source());
+            value->source);
         return false;
       }
     }
@@ -2798,7 +2795,7 @@
 bool Resolver::ValidateArrayConstructor(
     const ast::TypeConstructorExpression* ctor,
     const sem::Array* array_type) {
-  auto& values = ctor->values();
+  auto& values = ctor->values;
   auto* elem_type = array_type->ElemType();
   for (auto* value : values) {
     auto* value_type = TypeOf(value)->UnwrapRef();
@@ -2808,30 +2805,30 @@
           "expected '" +
               elem_type->FriendlyName(builder_->Symbols()) + "', found '" +
               TypeNameOf(value) + "'",
-          value->source());
+          value->source);
       return false;
     }
   }
 
   if (array_type->IsRuntimeSized()) {
-    AddError("cannot init a runtime-sized array", ctor->source());
+    AddError("cannot init a runtime-sized array", ctor->source);
     return false;
   } else if (!elem_type->IsConstructible()) {
     AddError("array constructor has non-constructible element type",
-             ctor->type()->As<ast::Array>()->type()->source());
+             ctor->type->As<ast::Array>()->type->source);
     return false;
   } else if (!values.empty() && (values.size() != array_type->Count())) {
     std::string fm = values.size() < array_type->Count() ? "few" : "many";
     AddError("array constructor has too " + fm + " elements: expected " +
                  std::to_string(array_type->Count()) + ", found " +
                  std::to_string(values.size()),
-             ctor->source());
+             ctor->source);
     return false;
   } else if (values.size() > array_type->Count()) {
     AddError("array constructor has too many elements: expected " +
                  std::to_string(array_type->Count()) + ", found " +
                  std::to_string(values.size()),
-             ctor->source());
+             ctor->source);
     return false;
   }
   return true;
@@ -2841,7 +2838,7 @@
     const ast::TypeConstructorExpression* ctor,
     const sem::Vector* vec_type,
     const std::string& type_name) {
-  auto& values = ctor->values();
+  auto& values = ctor->values;
   auto* elem_type = vec_type->type();
   size_t value_cardinality_sum = 0;
   for (auto* value : values) {
@@ -2853,7 +2850,7 @@
             "expected '" +
                 elem_type->FriendlyName(builder_->Symbols()) + "', found '" +
                 TypeNameOf(value) + "'",
-            value->source());
+            value->source);
         return false;
       }
 
@@ -2869,7 +2866,7 @@
             "expected '" +
                 elem_type->FriendlyName(builder_->Symbols()) + "', found '" +
                 value_elem_type->FriendlyName(builder_->Symbols()) + "'",
-            value->source());
+            value->source);
         return false;
       }
 
@@ -2878,7 +2875,7 @@
       // A vector constructor can only accept vectors and scalars.
       AddError("expected vector or scalar type in vector constructor; found: " +
                    value_type->FriendlyName(builder_->Symbols()),
-               value->source());
+               value->source);
       return false;
     }
   }
@@ -2891,8 +2888,8 @@
       TINT_ICE(Resolver, diagnostics_)
           << "constructor arguments expected to be non-empty!";
     }
-    const Source& values_start = values[0]->source();
-    const Source& values_end = values[values.size() - 1]->source();
+    const Source& values_start = values[0]->source;
+    const Source& values_end = values[values.size() - 1]->source;
     AddError("attempted to construct '" + type_name + "' with " +
                  std::to_string(value_cardinality_sum) + " component(s)",
              Source::Combine(values_start, values_end));
@@ -2922,20 +2919,20 @@
     const ast::TypeConstructorExpression* ctor,
     const sem::Matrix* matrix_type,
     const std::string& type_name) {
-  auto& values = ctor->values();
+  auto& values = ctor->values;
   // Zero Value expression
   if (values.empty()) {
     return true;
   }
 
-  if (!ValidateMatrix(matrix_type, ctor->source())) {
+  if (!ValidateMatrix(matrix_type, ctor->source)) {
     return false;
   }
 
   auto* elem_type = matrix_type->type();
   if (matrix_type->columns() != values.size()) {
-    const Source& values_start = values[0]->source();
-    const Source& values_end = values[values.size() - 1]->source();
+    const Source& values_start = values[0]->source;
+    const Source& values_end = values[values.size() - 1]->source;
     AddError("expected " + std::to_string(matrix_type->columns()) + " '" +
                  VectorPretty(matrix_type->rows(), elem_type) +
                  "' arguments in '" + type_name + "' constructor, found " +
@@ -2954,7 +2951,7 @@
                    VectorPretty(matrix_type->rows(), elem_type) + "' in '" +
                    type_name + "' constructor, found '" + TypeNameOf(value) +
                    "'",
-               value->source());
+               value->source);
       return false;
     }
   }
@@ -2966,18 +2963,18 @@
     const ast::TypeConstructorExpression* ctor,
     const sem::Type* type,
     const std::string& type_name) {
-  if (ctor->values().size() == 0) {
+  if (ctor->values.size() == 0) {
     return true;
   }
-  if (ctor->values().size() > 1) {
+  if (ctor->values.size() > 1) {
     AddError("expected zero or one value in constructor, got " +
-                 std::to_string(ctor->values().size()),
-             ctor->source());
+                 std::to_string(ctor->values.size()),
+             ctor->source);
     return false;
   }
 
   // Validate constructor
-  auto* value = ctor->values()[0];
+  auto* value = ctor->values[0];
   auto* value_type = TypeOf(value)->UnwrapRef();
 
   using Bool = sem::Bool;
@@ -2992,7 +2989,7 @@
   if (!is_valid) {
     AddError("cannot construct '" + type_name + "' with a value of type '" +
                  TypeNameOf(value) + "'",
-             ctor->source());
+             ctor->source);
 
     return false;
   }
@@ -3001,7 +2998,7 @@
 }
 
 bool Resolver::Identifier(ast::IdentifierExpression* expr) {
-  auto symbol = expr->symbol();
+  auto symbol = expr->symbol;
   VariableInfo* var;
   if (variable_stack_.get(symbol, &var)) {
     SetExprInfo(expr, var->type, var->type_name);
@@ -3022,22 +3019,22 @@
           auto& decls = loop_block->Decls();
           // If our identifier is in loop_block->decls, make sure its index is
           // less than first_continue
-          auto iter = std::find_if(
-              decls.begin(), decls.end(),
-              [&symbol](auto* v) { return v->symbol() == symbol; });
+          auto iter =
+              std::find_if(decls.begin(), decls.end(),
+                           [&symbol](auto* v) { return v->symbol == symbol; });
           if (iter != decls.end()) {
             auto var_decl_index =
                 static_cast<size_t>(std::distance(decls.begin(), iter));
             if (var_decl_index >= loop_block->NumDeclsAtFirstContinue()) {
               AddError("continue statement bypasses declaration of '" +
                            builder_->Symbols().NameFor(symbol) + "'",
-                       loop_block->FirstContinue()->source());
+                       loop_block->FirstContinue()->source);
               AddNote("identifier '" + builder_->Symbols().NameFor(symbol) +
                           "' declared here",
-                      (*iter)->source());
+                      (*iter)->source);
               AddNote("identifier '" + builder_->Symbols().NameFor(symbol) +
                           "' referenced in continuing block here",
-                      expr->source());
+                      expr->source);
               return false;
             }
           }
@@ -3050,30 +3047,30 @@
 
   auto iter = symbol_to_function_.find(symbol);
   if (iter != symbol_to_function_.end()) {
-    AddError("missing '(' for function call", expr->source().End());
+    AddError("missing '(' for function call", expr->source.End());
     return false;
   }
 
   std::string name = builder_->Symbols().NameFor(symbol);
   if (sem::ParseIntrinsicType(name) != IntrinsicType::kNone) {
-    AddError("missing '(' for intrinsic call", expr->source().End());
+    AddError("missing '(' for intrinsic call", expr->source.End());
     return false;
   }
 
-  AddError("identifier must be declared before use: " + name, expr->source());
+  AddError("identifier must be declared before use: " + name, expr->source);
   return false;
 }
 
 bool Resolver::MemberAccessor(ast::MemberAccessorExpression* expr) {
-  auto* structure = TypeOf(expr->structure());
+  auto* structure = TypeOf(expr->structure);
   auto* storage_type = structure->UnwrapRef();
 
   sem::Type* ret = nullptr;
   std::vector<uint32_t> swizzle;
 
   if (auto* str = storage_type->As<sem::Struct>()) {
-    Mark(expr->member());
-    auto symbol = expr->member()->symbol();
+    Mark(expr->member);
+    auto symbol = expr->member->symbol;
 
     const sem::StructMember* member = nullptr;
     for (auto* m : str->Members()) {
@@ -3087,7 +3084,7 @@
     if (ret == nullptr) {
       AddError(
           "struct member " + builder_->Symbols().NameFor(symbol) + " not found",
-          expr->source());
+          expr->source);
       return false;
     }
 
@@ -3100,8 +3097,8 @@
     builder_->Sem().Add(expr, builder_->create<sem::StructMemberAccess>(
                                   expr, ret, current_statement_, member));
   } else if (auto* vec = storage_type->As<sem::Vector>()) {
-    Mark(expr->member());
-    std::string s = builder_->Symbols().NameFor(expr->member()->symbol());
+    Mark(expr->member);
+    std::string s = builder_->Symbols().NameFor(expr->member->symbol);
     auto size = s.size();
     swizzle.reserve(s.size());
 
@@ -3125,18 +3122,18 @@
           break;
         default:
           AddError("invalid vector swizzle character",
-                   expr->member()->source().Begin() + swizzle.size());
+                   expr->member->source.Begin() + swizzle.size());
           return false;
       }
 
       if (swizzle.back() >= vec->Width()) {
-        AddError("invalid vector swizzle member", expr->member()->source());
+        AddError("invalid vector swizzle member", expr->member->source);
         return false;
       }
     }
 
     if (size < 1 || size > 4) {
-      AddError("invalid vector swizzle size", expr->member()->source());
+      AddError("invalid vector swizzle size", expr->member->source);
       return false;
     }
 
@@ -3150,7 +3147,7 @@
     if (!std::all_of(s.begin(), s.end(), is_rgba) &&
         !std::all_of(s.begin(), s.end(), is_xyzw)) {
       AddError("invalid mixing of vector swizzle characters rgba with xyzw",
-               expr->member()->source());
+               expr->member->source);
       return false;
     }
 
@@ -3174,8 +3171,8 @@
   } else {
     AddError(
         "invalid member accessor expression. Expected vector or struct, got '" +
-            TypeNameOf(expr->structure()) + "'",
-        expr->structure()->source());
+            TypeNameOf(expr->structure) + "'",
+        expr->structure->source);
     return false;
   }
 
@@ -3192,8 +3189,8 @@
   using Matrix = sem::Matrix;
   using Vector = sem::Vector;
 
-  auto* lhs_type = const_cast<sem::Type*>(TypeOf(expr->lhs())->UnwrapRef());
-  auto* rhs_type = const_cast<sem::Type*>(TypeOf(expr->rhs())->UnwrapRef());
+  auto* lhs_type = const_cast<sem::Type*>(TypeOf(expr->lhs)->UnwrapRef());
+  auto* rhs_type = const_cast<sem::Type*>(TypeOf(expr->rhs)->UnwrapRef());
 
   auto* lhs_vec = lhs_type->As<Vector>();
   auto* lhs_vec_elem_type = lhs_vec ? lhs_vec->type() : nullptr;
@@ -3383,14 +3380,14 @@
 
   AddError("Binary expression operand types are invalid for this operation: " +
                lhs_type->FriendlyName(builder_->Symbols()) + " " +
-               FriendlyName(expr->op()) + " " +
+               FriendlyName(expr->op) + " " +
                rhs_type->FriendlyName(builder_->Symbols()),
-           expr->source());
+           expr->source);
   return false;
 }
 
 bool Resolver::UnaryOp(ast::UnaryOpExpression* unary) {
-  auto* expr_type = TypeOf(unary->expr());
+  auto* expr_type = TypeOf(unary->expr);
   if (!expr_type) {
     return false;
   }
@@ -3398,40 +3395,39 @@
   std::string type_name;
   const sem::Type* type = nullptr;
 
-  switch (unary->op()) {
+  switch (unary->op) {
     case ast::UnaryOp::kNot:
       // Result type matches the deref'd inner type.
-      type_name = TypeNameOf(unary->expr());
+      type_name = TypeNameOf(unary->expr);
       type = expr_type->UnwrapRef();
       if (!type->Is<sem::Bool>() && !type->is_bool_vector()) {
         AddError("cannot logical negate expression of type '" +
-                     TypeNameOf(unary->expr()),
-                 unary->expr()->source());
+                     TypeNameOf(unary->expr),
+                 unary->expr->source);
         return false;
       }
       break;
 
     case ast::UnaryOp::kComplement:
       // Result type matches the deref'd inner type.
-      type_name = TypeNameOf(unary->expr());
+      type_name = TypeNameOf(unary->expr);
       type = expr_type->UnwrapRef();
       if (!type->is_integer_scalar_or_vector()) {
         AddError("cannot bitwise complement expression of type '" +
-                     TypeNameOf(unary->expr()),
-                 unary->expr()->source());
+                     TypeNameOf(unary->expr),
+                 unary->expr->source);
         return false;
       }
       break;
 
     case ast::UnaryOp::kNegation:
       // Result type matches the deref'd inner type.
-      type_name = TypeNameOf(unary->expr());
+      type_name = TypeNameOf(unary->expr);
       type = expr_type->UnwrapRef();
       if (!(type->IsAnyOf<sem::F32, sem::I32>() ||
             type->is_signed_integer_vector() || type->is_float_vector())) {
-        AddError(
-            "cannot negate expression of type '" + TypeNameOf(unary->expr()),
-            unary->expr()->source());
+        AddError("cannot negate expression of type '" + TypeNameOf(unary->expr),
+                 unary->expr->source);
         return false;
       }
       break;
@@ -3441,14 +3437,13 @@
         if (ref->StoreType()->UnwrapRef()->is_handle()) {
           AddError(
               "cannot take the address of expression in handle storage class",
-              unary->expr()->source());
+              unary->expr->source);
           return false;
         }
         type = builder_->create<sem::Pointer>(
             ref->StoreType(), ref->StorageClass(), ref->Access());
       } else {
-        AddError("cannot take the address of expression",
-                 unary->expr()->source());
+        AddError("cannot take the address of expression", unary->expr->source);
         return false;
       }
       break;
@@ -3459,8 +3454,8 @@
             ptr->StoreType(), ptr->StorageClass(), ptr->Access());
       } else {
         AddError("cannot dereference expression of type '" +
-                     TypeNameOf(unary->expr()) + "'",
-                 unary->expr()->source());
+                     TypeNameOf(unary->expr) + "'",
+                 unary->expr->source);
         return false;
       }
       break;
@@ -3471,10 +3466,10 @@
 }
 
 bool Resolver::VariableDeclStatement(const ast::VariableDeclStatement* stmt) {
-  ast::Variable* var = stmt->variable();
+  ast::Variable* var = stmt->variable;
   Mark(var);
 
-  if (!ValidateNoDuplicateDefinition(var->symbol(), var->source())) {
+  if (!ValidateNoDuplicateDefinition(var->symbol, var->source)) {
     return false;
   }
 
@@ -3483,15 +3478,15 @@
     return false;
   }
 
-  for (auto* deco : var->decorations()) {
+  for (auto* deco : var->decorations) {
     Mark(deco);
     if (!deco->Is<ast::InternalDecoration>()) {
-      AddError("decorations are not valid on local variables", deco->source());
+      AddError("decorations are not valid on local variables", deco->source);
       return false;
     }
   }
 
-  variable_stack_.set(var->symbol(), info);
+  variable_stack_.set(var->symbol, info);
   if (current_block_) {  // Not all statements are inside a block
     current_block_->AddDecl(var);
   }
@@ -3500,18 +3495,18 @@
     return false;
   }
 
-  if (!var->is_const() &&
-      IsValidationEnabled(var->decorations(),
+  if (!var->is_const &&
+      IsValidationEnabled(var->decorations,
                           ast::DisabledValidation::kIgnoreStorageClass)) {
     if (!info->type->UnwrapRef()->IsConstructible()) {
       AddError("function variable must have a constructible type",
-               var->type() ? var->type()->source() : var->source());
+               var->type ? var->type->source : var->source);
       return false;
     }
     if (info->storage_class != ast::StorageClass::kFunction) {
       if (info->storage_class != ast::StorageClass::kNone) {
         AddError("function variable has a non-function storage class",
-                 stmt->source());
+                 stmt->source);
         return false;
       }
       info->storage_class = ast::StorageClass::kFunction;
@@ -3519,10 +3514,10 @@
   }
 
   if (!ApplyStorageClassUsageToType(info->storage_class, info->type,
-                                    var->source())) {
+                                    var->source)) {
     AddNote("while instantiating variable " +
-                builder_->Symbols().NameFor(var->symbol()),
-            var->source());
+                builder_->Symbols().NameFor(var->symbol),
+            var->source);
     return false;
   }
 
@@ -3532,7 +3527,7 @@
 sem::Type* Resolver::TypeDecl(const ast::TypeDecl* named_type) {
   sem::Type* result = nullptr;
   if (auto* alias = named_type->As<ast::Alias>()) {
-    result = Type(alias->type());
+    result = Type(alias->type);
   } else if (auto* str = named_type->As<ast::Struct>()) {
     result = Structure(str);
   } else {
@@ -3543,8 +3538,7 @@
     return nullptr;
   }
 
-  named_type_info_.emplace(named_type->name(),
-                           TypeDeclInfo{named_type, result});
+  named_type_info_.emplace(named_type->name, TypeDeclInfo{named_type, result});
 
   if (!ValidateTypeDecl(named_type)) {
     return nullptr;
@@ -3555,17 +3549,17 @@
 }
 
 bool Resolver::ValidateTypeDecl(const ast::TypeDecl* named_type) const {
-  auto iter = named_type_info_.find(named_type->name());
+  auto iter = named_type_info_.find(named_type->name);
   if (iter == named_type_info_.end()) {
     TINT_ICE(Resolver, diagnostics_)
         << "ValidateTypeDecl called() before TypeDecl()";
   }
   if (iter->second.ast != named_type) {
     AddError("type with the name '" +
-                 builder_->Symbols().NameFor(named_type->name()) +
+                 builder_->Symbols().NameFor(named_type->name) +
                  "' was already declared",
-             named_type->source());
-    AddNote("first declared here", iter->second.ast->source());
+             named_type->source);
+    AddNote("first declared here", iter->second.ast->source);
     return false;
   }
   return true;
@@ -3624,7 +3618,7 @@
 bool Resolver::ValidatePipelineStages() {
   auto check_workgroup_storage = [&](FunctionInfo* func,
                                      FunctionInfo* entry_point) {
-    auto stage = entry_point->declaration->pipeline_stage();
+    auto stage = entry_point->declaration->PipelineStage();
     if (stage != ast::PipelineStage::kCompute) {
       for (auto* var : func->local_referenced_module_vars) {
         if (var->storage_class == ast::StorageClass::kWorkgroup) {
@@ -3633,29 +3627,28 @@
           for (auto* user : var->users) {
             auto it = expr_info_.find(user->As<ast::Expression>());
             if (it != expr_info_.end()) {
-              if (func->declaration->symbol() ==
-                  it->second.statement->Function()->symbol()) {
+              if (func->declaration->symbol ==
+                  it->second.statement->Function()->symbol) {
                 AddError("workgroup memory cannot be used by " +
                              stage_name.str() + " pipeline stage",
-                         user->source());
+                         user->source);
                 break;
               }
             }
           }
-          AddNote("variable is declared here", var->declaration->source());
+          AddNote("variable is declared here", var->declaration->source);
           if (func != entry_point) {
             TraverseCallChain(entry_point, func, [&](FunctionInfo* f) {
-              AddNote(
-                  "called by function '" +
-                      builder_->Symbols().NameFor(f->declaration->symbol()) +
-                      "'",
-                  f->declaration->source());
+              AddNote("called by function '" +
+                          builder_->Symbols().NameFor(f->declaration->symbol) +
+                          "'",
+                      f->declaration->source);
             });
             AddNote("called by entry point '" +
                         builder_->Symbols().NameFor(
-                            entry_point->declaration->symbol()) +
+                            entry_point->declaration->symbol) +
                         "'",
-                    entry_point->declaration->source());
+                    entry_point->declaration->source);
           }
           return false;
         }
@@ -3677,24 +3670,24 @@
 
   auto check_intrinsic_calls = [&](FunctionInfo* func,
                                    FunctionInfo* entry_point) {
-    auto stage = entry_point->declaration->pipeline_stage();
+    auto stage = entry_point->declaration->PipelineStage();
     for (auto& call : func->intrinsic_calls) {
       if (!call.intrinsic->SupportedStages().Contains(stage)) {
         std::stringstream err;
         err << "built-in cannot be used by " << stage << " pipeline stage";
-        AddError(err.str(), call.call->source());
+        AddError(err.str(), call.call->source);
         if (func != entry_point) {
           TraverseCallChain(entry_point, func, [&](FunctionInfo* f) {
             AddNote("called by function '" +
-                        builder_->Symbols().NameFor(f->declaration->symbol()) +
+                        builder_->Symbols().NameFor(f->declaration->symbol) +
                         "'",
-                    f->declaration->source());
+                    f->declaration->source);
           });
           AddNote("called by entry point '" +
                       builder_->Symbols().NameFor(
-                          entry_point->declaration->symbol()) +
+                          entry_point->declaration->symbol) +
                       "'",
-                  entry_point->declaration->source());
+                  entry_point->declaration->source);
         }
         return false;
       }
@@ -3742,8 +3735,8 @@
   std::unordered_map<Symbol, std::vector<Symbol>> ancestor_entry_points;
   for (auto* entry_point : entry_points_) {
     for (auto* call : entry_point->transitive_calls) {
-      auto& vec = ancestor_entry_points[call->declaration->symbol()];
-      vec.emplace_back(entry_point->declaration->symbol());
+      auto& vec = ancestor_entry_points[call->declaration->symbol];
+      vec.emplace_back(entry_point->declaration->symbol);
     }
   }
 
@@ -3755,7 +3748,7 @@
 
     sem::Variable* sem_var = nullptr;
 
-    if (ast::HasDecoration<ast::OverrideDecoration>(var->decorations())) {
+    if (ast::HasDecoration<ast::OverrideDecoration>(var->decorations)) {
       // Create a pipeline overridable constant.
       sem_var = builder_->create<sem::GlobalVariable>(var, info->type,
                                                       info->constant_id);
@@ -3829,7 +3822,7 @@
         info->declaration, const_cast<sem::Type*>(info->return_type),
         parameters, remap_vars(info->referenced_module_vars),
         remap_vars(info->local_referenced_module_vars), info->return_statements,
-        info->callsites, ancestor_entry_points[func->symbol()],
+        info->callsites, ancestor_entry_points[func->symbol],
         info->workgroup_size);
     func_info_to_sem_func.emplace(info, sem_func);
     sem.Add(func, sem_func);
@@ -3858,9 +3851,9 @@
 }
 
 sem::Array* Resolver::Array(const ast::Array* arr) {
-  auto source = arr->source();
+  auto source = arr->source;
 
-  auto* elem_type = Type(arr->type());
+  auto* elem_type = Type(arr->type);
   if (!elem_type) {
     return nullptr;
   }
@@ -3875,23 +3868,23 @@
   uint32_t el_align = elem_type->Align();
   uint32_t el_size = elem_type->Size();
 
-  if (!ValidateNoDuplicateDecorations(arr->decorations())) {
+  if (!ValidateNoDuplicateDecorations(arr->decorations)) {
     return nullptr;
   }
 
   // Look for explicit stride via [[stride(n)]] decoration
   uint32_t explicit_stride = 0;
-  for (auto* deco : arr->decorations()) {
+  for (auto* deco : arr->decorations) {
     Mark(deco);
     if (auto* sd = deco->As<ast::StrideDecoration>()) {
-      explicit_stride = sd->stride();
+      explicit_stride = sd->stride;
       if (!ValidateArrayStrideDecoration(sd, el_size, el_align, source)) {
         return nullptr;
       }
       continue;
     }
 
-    AddError("decoration is not valid for array types", deco->source());
+    AddError("decoration is not valid for array types", deco->source);
     return nullptr;
   }
 
@@ -3903,13 +3896,13 @@
   // Evaluate the constant array size expression.
   // sem::Array uses a size of 0 for a runtime-sized array.
   uint32_t count = 0;
-  if (auto* count_expr = arr->Size()) {
+  if (auto* count_expr = arr->count) {
     Mark(count_expr);
     if (!Expression(count_expr)) {
       return nullptr;
     }
 
-    auto size_source = count_expr->source();
+    auto size_source = count_expr->source;
 
     auto* ty = TypeOf(count_expr)->UnwrapRef();
     if (!ty->is_integer_scalar()) {
@@ -3921,20 +3914,20 @@
       // Make sure the identifier is a non-overridable module-scope constant.
       VariableInfo* var = nullptr;
       bool is_global = false;
-      if (!variable_stack_.get(ident->symbol(), &var, &is_global) ||
-          !is_global || !var->declaration->is_const()) {
+      if (!variable_stack_.get(ident->symbol, &var, &is_global) || !is_global ||
+          !var->declaration->is_const) {
         AddError("array size identifier must be a module-scope constant",
                  size_source);
         return nullptr;
       }
       if (ast::HasDecoration<ast::OverrideDecoration>(
-              var->declaration->decorations())) {
+              var->declaration->decorations)) {
         AddError("array size expression must not be pipeline-overridable",
                  size_source);
         return nullptr;
       }
 
-      count_expr = var->declaration->constructor();
+      count_expr = var->declaration->constructor;
     } else if (!count_expr->Is<ast::ScalarConstructorExpression>()) {
       AddError(
           "array size expression must be either a literal or a module-scope "
@@ -3965,7 +3958,7 @@
     msg << "array size in bytes must not exceed 0x" << std::hex
         << std::numeric_limits<uint32_t>::max() << ", but is 0x" << std::hex
         << size;
-    AddError(msg.str(), arr->source());
+    AddError(msg.str(), arr->source);
     return nullptr;
   }
   if (stride > std::numeric_limits<uint32_t>::max() ||
@@ -3983,7 +3976,7 @@
   }
 
   if (elem_type->Is<sem::Atomic>()) {
-    atomic_composite_info_.emplace(out, arr->type()->source());
+    atomic_composite_info_.emplace(out, arr->type->source);
   } else {
     auto found = atomic_composite_info_.find(elem_type);
     if (found != atomic_composite_info_.end()) {
@@ -4017,7 +4010,7 @@
                                              uint32_t el_size,
                                              uint32_t el_align,
                                              const Source& source) {
-  auto stride = deco->stride();
+  auto stride = deco->stride;
   bool is_valid_stride =
       (stride >= el_size) && (stride >= el_align) && (stride % el_align == 0);
   if (!is_valid_stride) {
@@ -4038,7 +4031,7 @@
 bool Resolver::ValidateStructure(const sem::Struct* str) {
   if (str->Members().empty()) {
     AddError("structures must have at least one member",
-             str->Declaration()->source());
+             str->Declaration()->source);
     return false;
   }
 
@@ -4049,15 +4042,15 @@
         if (member != str->Members().back()) {
           AddError(
               "runtime arrays may only appear as the last member of a struct",
-              member->Declaration()->source());
+              member->Declaration()->source);
           return false;
         }
         if (!str->IsBlockDecorated()) {
           AddError(
               "a struct containing a runtime-sized array "
               "requires the [[block]] attribute: '" +
-                  builder_->Symbols().NameFor(str->Declaration()->name()) + "'",
-              member->Declaration()->source());
+                  builder_->Symbols().NameFor(str->Declaration()->name) + "'",
+              member->Declaration()->source);
           return false;
         }
       }
@@ -4065,7 +4058,7 @@
 
     auto has_position = false;
     ast::InvariantDecoration* invariant_attribute = nullptr;
-    for (auto* deco : member->Declaration()->decorations()) {
+    for (auto* deco : member->Declaration()->decorations) {
       if (!deco->IsAnyOf<ast::BuiltinDecoration,             //
                          ast::InternalDecoration,            //
                          ast::InterpolateDecoration,         //
@@ -4076,12 +4069,11 @@
                          ast::StructMemberAlignDecoration>()) {
         if (deco->Is<ast::StrideDecoration>() &&
             IsValidationDisabled(
-                member->Declaration()->decorations(),
+                member->Declaration()->decorations,
                 ast::DisabledValidation::kIgnoreStrideDecoration)) {
           continue;
         }
-        AddError("decoration is not valid for structure members",
-                 deco->source());
+        AddError("decoration is not valid for structure members", deco->source);
         return false;
       }
 
@@ -4089,7 +4081,7 @@
         invariant_attribute = invariant;
       } else if (auto* location = deco->As<ast::LocationDecoration>()) {
         if (!ValidateLocationDecoration(location, member->Type(), locations,
-                                        member->Declaration()->source())) {
+                                        member->Declaration()->source)) {
           return false;
         }
       } else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
@@ -4097,7 +4089,7 @@
                                        /* is_input */ false)) {
           return false;
         }
-        if (builtin->value() == ast::Builtin::kPosition) {
+        if (builtin->builtin == ast::Builtin::kPosition) {
           has_position = true;
         }
       } else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) {
@@ -4109,27 +4101,26 @@
 
     if (invariant_attribute && !has_position) {
       AddError("invariant attribute must only be applied to a position builtin",
-               invariant_attribute->source());
+               invariant_attribute->source);
       return false;
     }
 
     if (auto* member_struct_type = member->Type()->As<sem::Struct>()) {
       if (auto* member_struct_type_block_decoration =
               ast::GetDecoration<ast::StructBlockDecoration>(
-                  member_struct_type->Declaration()->decorations())) {
+                  member_struct_type->Declaration()->decorations)) {
         AddError("structs must not contain [[block]] decorated struct members",
-                 member->Declaration()->source());
+                 member->Declaration()->source);
         AddNote("see member's struct decoration here",
-                member_struct_type_block_decoration->source());
+                member_struct_type_block_decoration->source);
         return false;
       }
     }
   }
 
-  for (auto* deco : str->Declaration()->decorations()) {
+  for (auto* deco : str->Declaration()->decorations) {
     if (!(deco->Is<ast::StructBlockDecoration>())) {
-      AddError("decoration is not valid for struct declarations",
-               deco->source());
+      AddError("decoration is not valid for struct declarations", deco->source);
       return false;
     }
   }
@@ -4144,10 +4135,10 @@
     const Source& source,
     const bool is_input) {
   std::string inputs_or_output = is_input ? "inputs" : "output";
-  if (current_function_ && current_function_->declaration->pipeline_stage() ==
+  if (current_function_ && current_function_->declaration->PipelineStage() ==
                                ast::PipelineStage::kCompute) {
     AddError("decoration is not valid for compute shader " + inputs_or_output,
-             location->source());
+             location->source);
     return false;
   }
 
@@ -4159,30 +4150,30 @@
     AddNote(
         "'location' attribute must only be applied to declarations of "
         "numeric scalar or numeric vector type",
-        location->source());
+        location->source);
     return false;
   }
 
-  if (locations.count(location->value())) {
+  if (locations.count(location->value)) {
     AddError(deco_to_str(location) + " attribute appears multiple times",
-             location->source());
+             location->source);
     return false;
   }
-  locations.emplace(location->value());
+  locations.emplace(location->value);
 
   return true;
 }
 
 sem::Struct* Resolver::Structure(const ast::Struct* str) {
-  if (!ValidateNoDuplicateDecorations(str->decorations())) {
+  if (!ValidateNoDuplicateDecorations(str->decorations)) {
     return nullptr;
   }
-  for (auto* deco : str->decorations()) {
+  for (auto* deco : str->decorations) {
     Mark(deco);
   }
 
   sem::StructMemberList sem_members;
-  sem_members.reserve(str->members().size());
+  sem_members.reserve(str->members.size());
 
   // Calculate the effective size and alignment of each field, and the overall
   // size of the structure.
@@ -4198,19 +4189,19 @@
   uint64_t struct_align = 1;
   std::unordered_map<Symbol, ast::StructMember*> member_map;
 
-  for (auto* member : str->members()) {
+  for (auto* member : str->members) {
     Mark(member);
-    auto result = member_map.emplace(member->symbol(), member);
+    auto result = member_map.emplace(member->symbol, member);
     if (!result.second) {
       AddError("redefinition of '" +
-                   builder_->Symbols().NameFor(member->symbol()) + "'",
-               member->source());
-      AddNote("previous definition is here", result.first->second->source());
+                   builder_->Symbols().NameFor(member->symbol) + "'",
+               member->source);
+      AddNote("previous definition is here", result.first->second->source);
       return nullptr;
     }
 
     // Resolve member type
-    auto* type = Type(member->type());
+    auto* type = Type(member->type);
     if (!type) {
       return nullptr;
     }
@@ -4219,7 +4210,7 @@
     if (!IsPlain(type)) {
       AddError(type->FriendlyName(builder_->Symbols()) +
                    " cannot be used as the type of a structure member",
-               member->source());
+               member->source);
       return nullptr;
     }
 
@@ -4227,41 +4218,41 @@
     uint64_t align = type->Align();
     uint64_t size = type->Size();
 
-    if (!ValidateNoDuplicateDecorations(member->decorations())) {
+    if (!ValidateNoDuplicateDecorations(member->decorations)) {
       return nullptr;
     }
 
     bool has_offset_deco = false;
     bool has_align_deco = false;
     bool has_size_deco = false;
-    for (auto* deco : member->decorations()) {
+    for (auto* deco : member->decorations) {
       Mark(deco);
       if (auto* o = deco->As<ast::StructMemberOffsetDecoration>()) {
         // Offset decorations are not part of the WGSL spec, but are emitted
         // by the SPIR-V reader.
-        if (o->offset() < struct_size) {
-          AddError("offsets must be in ascending order", o->source());
+        if (o->offset < struct_size) {
+          AddError("offsets must be in ascending order", o->source);
           return nullptr;
         }
-        offset = o->offset();
+        offset = o->offset;
         align = 1;
         has_offset_deco = true;
       } else if (auto* a = deco->As<ast::StructMemberAlignDecoration>()) {
-        if (a->align() <= 0 || !utils::IsPowerOfTwo(a->align())) {
+        if (a->align <= 0 || !utils::IsPowerOfTwo(a->align)) {
           AddError("align value must be a positive, power-of-two integer",
-                   a->source());
+                   a->source);
           return nullptr;
         }
-        align = a->align();
+        align = a->align;
         has_align_deco = true;
       } else if (auto* s = deco->As<ast::StructMemberSizeDecoration>()) {
-        if (s->size() < size) {
+        if (s->size < size) {
           AddError("size must be at least as big as the type's size (" +
                        std::to_string(size) + ")",
-                   s->source());
+                   s->source);
           return nullptr;
         }
-        size = s->size();
+        size = s->size;
         has_size_deco = true;
       }
     }
@@ -4269,7 +4260,7 @@
     if (has_offset_deco && (has_align_deco || has_size_deco)) {
       AddError(
           "offset decorations cannot be used with align or size decorations",
-          member->source());
+          member->source);
       return nullptr;
     }
 
@@ -4279,12 +4270,12 @@
       msg << "struct member has byte offset 0x" << std::hex << offset
           << ", but must not exceed 0x" << std::hex
           << std::numeric_limits<uint32_t>::max();
-      AddError(msg.str(), member->source());
+      AddError(msg.str(), member->source);
       return nullptr;
     }
 
     auto* sem_member = builder_->create<sem::StructMember>(
-        member, member->symbol(), const_cast<sem::Type*>(type),
+        member, member->symbol, const_cast<sem::Type*>(type),
         static_cast<uint32_t>(sem_members.size()),
         static_cast<uint32_t>(offset), static_cast<uint32_t>(align),
         static_cast<uint32_t>(size));
@@ -4303,7 +4294,7 @@
     msg << "struct size in bytes must not exceed 0x" << std::hex
         << std::numeric_limits<uint32_t>::max() << ", but is 0x" << std::hex
         << struct_size;
-    AddError(msg.str(), str->source());
+    AddError(msg.str(), str->source);
     return nullptr;
   }
   if (struct_align > std::numeric_limits<uint32_t>::max()) {
@@ -4313,7 +4304,7 @@
   }
 
   auto* out = builder_->create<sem::Struct>(
-      str, str->name(), sem_members, static_cast<uint32_t>(struct_align),
+      str, str->name, sem_members, static_cast<uint32_t>(struct_align),
       static_cast<uint32_t>(struct_size),
       static_cast<uint32_t>(size_no_padding));
 
@@ -4321,7 +4312,7 @@
     auto* mem_type = sem_members[i]->Type();
     if (mem_type->Is<sem::Atomic>()) {
       atomic_composite_info_.emplace(out,
-                                     sem_members[i]->Declaration()->source());
+                                     sem_members[i]->Declaration()->source);
       break;
     } else {
       auto found = atomic_composite_info_.find(mem_type);
@@ -4342,8 +4333,8 @@
 bool Resolver::ValidateReturn(const ast::ReturnStatement* ret) {
   auto* func_type = current_function_->return_type;
 
-  auto* ret_type = ret->has_value() ? TypeOf(ret->value())->UnwrapRef()
-                                    : builder_->create<sem::Void>();
+  auto* ret_type = ret->value ? TypeOf(ret->value)->UnwrapRef()
+                              : builder_->create<sem::Void>();
 
   if (func_type->UnwrapRef() != ret_type) {
     AddError(
@@ -4351,7 +4342,7 @@
         "return type, returned '" +
             ret_type->FriendlyName(builder_->Symbols()) + "', expected '" +
             current_function_->return_type_name + "'",
-        ret->source());
+        ret->source);
     return false;
   }
 
@@ -4359,9 +4350,9 @@
   if (auto* continuing =
           sem->FindFirstParent<sem::LoopContinuingBlockStatement>()) {
     AddError("continuing blocks must not contain a return statement",
-             ret->source());
+             ret->source);
     if (continuing != sem->Parent()) {
-      AddNote("see continuing block here", continuing->Declaration()->source());
+      AddNote("see continuing block here", continuing->Declaration()->source);
     }
     return false;
   }
@@ -4372,7 +4363,7 @@
 bool Resolver::Return(ast::ReturnStatement* ret) {
   current_function_->return_statements.push_back(ret);
 
-  if (auto* value = ret->value()) {
+  if (auto* value = ret->value) {
     Mark(value);
     if (!Expression(value)) {
       return false;
@@ -4385,66 +4376,66 @@
 }
 
 bool Resolver::ValidateSwitch(const ast::SwitchStatement* s) {
-  auto* cond_type = TypeOf(s->condition())->UnwrapRef();
+  auto* cond_type = TypeOf(s->condition)->UnwrapRef();
   if (!cond_type->is_integer_scalar()) {
     AddError(
         "switch statement selector expression must be of a "
         "scalar integer type",
-        s->condition()->source());
+        s->condition->source);
     return false;
   }
 
   bool has_default = false;
   std::unordered_map<uint32_t, Source> selectors;
 
-  for (auto* case_stmt : s->body()) {
+  for (auto* case_stmt : s->body) {
     if (case_stmt->IsDefault()) {
       if (has_default) {
         // More than one default clause
         AddError("switch statement must have exactly one default clause",
-                 case_stmt->source());
+                 case_stmt->source);
         return false;
       }
       has_default = true;
     }
 
-    for (auto* selector : case_stmt->selectors()) {
+    for (auto* selector : case_stmt->selectors) {
       if (cond_type != TypeOf(selector)) {
         AddError(
             "the case selector values must have the same "
             "type as the selector expression.",
-            case_stmt->source());
+            case_stmt->source);
         return false;
       }
 
-      auto v = selector->value_as_u32();
+      auto v = selector->ValueAsU32();
       auto it = selectors.find(v);
       if (it != selectors.end()) {
         auto val = selector->Is<ast::IntLiteral>()
-                       ? std::to_string(selector->value_as_i32())
-                       : std::to_string(selector->value_as_u32());
-        AddError("duplicate switch case '" + val + "'", selector->source());
+                       ? std::to_string(selector->ValueAsI32())
+                       : std::to_string(selector->ValueAsU32());
+        AddError("duplicate switch case '" + val + "'", selector->source);
         AddNote("previous case declared here", it->second);
         return false;
       }
-      selectors.emplace(v, selector->source());
+      selectors.emplace(v, selector->source);
     }
   }
 
   if (!has_default) {
     // No default clause
-    AddError("switch statement must have a default clause", s->source());
+    AddError("switch statement must have a default clause", s->source);
     return false;
   }
 
-  if (!s->body().empty()) {
-    auto* last_clause = s->body().back()->As<ast::CaseStatement>();
-    auto* last_stmt = last_clause->body()->last();
+  if (!s->body.empty()) {
+    auto* last_clause = s->body.back()->As<ast::CaseStatement>();
+    auto* last_stmt = last_clause->body->Last();
     if (last_stmt && last_stmt->Is<ast::FallthroughStatement>()) {
       AddError(
           "a fallthrough statement must not appear as "
           "the last statement in last clause of a switch",
-          last_stmt->source());
+          last_stmt->source);
       return false;
     }
   }
@@ -4457,11 +4448,11 @@
       builder_->create<sem::SwitchStatement>(stmt, current_compound_statement_);
   builder_->Sem().Add(stmt, sem);
   return Scope(sem, [&] {
-    Mark(stmt->condition());
-    if (!Expression(stmt->condition())) {
+    Mark(stmt->condition);
+    if (!Expression(stmt->condition)) {
       return false;
     }
-    for (auto* case_stmt : stmt->body()) {
+    for (auto* case_stmt : stmt->body) {
       Mark(case_stmt);
       if (!CaseStatement(case_stmt)) {
         return false;
@@ -4475,10 +4466,10 @@
 }
 
 bool Resolver::Assignment(ast::AssignmentStatement* a) {
-  Mark(a->lhs());
-  Mark(a->rhs());
+  Mark(a->lhs);
+  Mark(a->rhs);
 
-  if (!Expression(a->lhs()) || !Expression(a->rhs())) {
+  if (!Expression(a->lhs) || !Expression(a->rhs)) {
     return false;
   }
   return ValidateAssignment(a);
@@ -4486,24 +4477,24 @@
 
 bool Resolver::ValidateAssignment(const ast::AssignmentStatement* a) {
   // https://gpuweb.github.io/gpuweb/wgsl/#assignment-statement
-  auto const* lhs_type = TypeOf(a->lhs());
-  auto const* rhs_type = TypeOf(a->rhs());
+  auto const* lhs_type = TypeOf(a->lhs);
+  auto const* rhs_type = TypeOf(a->rhs);
 
-  if (auto* ident = a->lhs()->As<ast::IdentifierExpression>()) {
+  if (auto* ident = a->lhs->As<ast::IdentifierExpression>()) {
     VariableInfo* var;
-    if (variable_stack_.get(ident->symbol(), &var)) {
+    if (variable_stack_.get(ident->symbol, &var)) {
       if (var->kind == VariableKind::kParameter) {
-        AddError("cannot assign to function parameter", a->lhs()->source());
-        AddNote("'" + builder_->Symbols().NameFor(ident->symbol()) +
+        AddError("cannot assign to function parameter", a->lhs->source);
+        AddNote("'" + builder_->Symbols().NameFor(ident->symbol) +
                     "' is declared here:",
-                var->declaration->source());
+                var->declaration->source);
         return false;
       }
-      if (var->declaration->is_const()) {
-        AddError("cannot assign to const", a->lhs()->source());
-        AddNote("'" + builder_->Symbols().NameFor(ident->symbol()) +
+      if (var->declaration->is_const) {
+        AddError("cannot assign to const", a->lhs->source);
+        AddNote("'" + builder_->Symbols().NameFor(ident->symbol) +
                     "' is declared here:",
-                var->declaration->source());
+                var->declaration->source);
         return false;
       }
     }
@@ -4512,8 +4503,8 @@
   auto* lhs_ref = lhs_type->As<sem::Reference>();
   if (!lhs_ref) {
     // LHS is not a reference, so it has no storage.
-    AddError("cannot assign to value of type '" + TypeNameOf(a->lhs()) + "'",
-             a->lhs()->source());
+    AddError("cannot assign to value of type '" + TypeNameOf(a->lhs) + "'",
+             a->lhs->source);
     return false;
   }
 
@@ -4522,19 +4513,18 @@
 
   // Value type has to match storage type
   if (storage_type != value_type) {
-    AddError("cannot assign '" + TypeNameOf(a->rhs()) + "' to '" +
-                 TypeNameOf(a->lhs()) + "'",
-             a->source());
+    AddError("cannot assign '" + TypeNameOf(a->rhs) + "' to '" +
+                 TypeNameOf(a->lhs) + "'",
+             a->source);
     return false;
   }
   if (!storage_type->IsConstructible()) {
-    AddError("storage type of assignment must be constructible", a->source());
+    AddError("storage type of assignment must be constructible", a->source);
     return false;
   }
   if (lhs_ref->Access() == ast::Access::kRead) {
-    AddError(
-        "cannot store into a read-only type '" + TypeNameOf(a->lhs()) + "'",
-        a->source());
+    AddError("cannot store into a read-only type '" + TypeNameOf(a->lhs) + "'",
+             a->source);
     return false;
   }
   return true;
@@ -4550,7 +4540,7 @@
       if (is_global) {
         AddError("redefinition of '" + builder_->Symbols().NameFor(sym) + "'",
                  source);
-        AddNote("previous definition is here", var->declaration->source());
+        AddNote("previous definition is here", var->declaration->source);
         return false;
       }
     }
@@ -4558,7 +4548,7 @@
     if (it != symbol_to_function_.end()) {
       AddError("redefinition of '" + builder_->Symbols().NameFor(sym) + "'",
                source);
-      AddNote("previous definition is here", it->second->declaration->source());
+      AddNote("previous definition is here", it->second->declaration->source);
       return false;
     }
   } else {
@@ -4566,7 +4556,7 @@
     if (variable_stack_.get(sym, &var)) {
       AddError("redefinition of '" + builder_->Symbols().NameFor(sym) + "'",
                source);
-      AddNote("previous definition is here", var->declaration->source());
+      AddNote("previous definition is here", var->declaration->source);
       return false;
     }
   }
@@ -4577,9 +4567,9 @@
     const ast::DecorationList& decorations) {
   std::unordered_map<const TypeInfo*, Source> seen;
   for (auto* d : decorations) {
-    auto res = seen.emplace(&d->TypeInfo(), d->source());
+    auto res = seen.emplace(&d->TypeInfo(), d->source);
     if (!res.second && !d->Is<ast::InternalDecoration>()) {
-      AddError("duplicate " + d->name() + " decoration", d->source());
+      AddError("duplicate " + d->Name() + " decoration", d->source);
       AddNote("first decoration declared here", res.first->second);
       return false;
     }
@@ -4604,8 +4594,8 @@
         std::stringstream err;
         err << "while analysing structure member "
             << str->FriendlyName(builder_->Symbols()) << "."
-            << builder_->Symbols().NameFor(member->Declaration()->symbol());
-        AddNote(err.str(), member->Declaration()->source());
+            << builder_->Symbols().NameFor(member->Declaration()->symbol);
+        AddNote(err.str(), member->Declaration()->source);
         return false;
       }
     }
@@ -4665,7 +4655,7 @@
   TINT_ICE(Resolver, diagnostics_)
       << "AST node '" << node->TypeInfo().name
       << "' was encountered twice in the same AST of a Program\n"
-      << "At: " << node->source() << "\n"
+      << "At: " << node->source << "\n"
       << "Pointer: " << node;
 }
 
diff --git a/src/resolver/resolver_constants.cc b/src/resolver/resolver_constants.cc
index dc453cc..e28ed03 100644
--- a/src/resolver/resolver_constants.cc
+++ b/src/resolver/resolver_constants.cc
@@ -80,18 +80,18 @@
 sem::Constant Resolver::EvaluateConstantValue(
     const ast::ScalarConstructorExpression* scalar_ctor,
     const sem::Type* type) {
-  auto* literal = scalar_ctor->literal();
+  auto* literal = scalar_ctor->literal;
   if (auto* lit = literal->As<ast::SintLiteral>()) {
-    return {type, {lit->value_as_i32()}};
+    return {type, {lit->ValueAsI32()}};
   }
   if (auto* lit = literal->As<ast::UintLiteral>()) {
-    return {type, {lit->value_as_u32()}};
+    return {type, {lit->ValueAsU32()}};
   }
   if (auto* lit = literal->As<ast::FloatLiteral>()) {
-    return {type, {lit->value()}};
+    return {type, {lit->value}};
   }
   if (auto* lit = literal->As<ast::BoolLiteral>()) {
-    return {type, {lit->IsTrue()}};
+    return {type, {lit->value}};
   }
   TINT_UNREACHABLE(Resolver, builder_->Diagnostics());
   return {};
@@ -100,7 +100,7 @@
 sem::Constant Resolver::EvaluateConstantValue(
     const ast::TypeConstructorExpression* type_ctor,
     const sem::Type* type) {
-  auto& ctor_values = type_ctor->values();
+  auto& ctor_values = type_ctor->values;
   auto* vec = type->As<sem::Vector>();
 
   // For now, only fold scalars and vectors
diff --git a/src/resolver/resolver_test.cc b/src/resolver/resolver_test.cc
index 024d07d..776cf4c 100644
--- a/src/resolver/resolver_test.cc
+++ b/src/resolver/resolver_test.cc
@@ -175,12 +175,12 @@
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 
-  ASSERT_NE(TypeOf(stmt->condition()), nullptr);
+  ASSERT_NE(TypeOf(stmt->condition), nullptr);
   ASSERT_NE(TypeOf(else_lhs), nullptr);
   ASSERT_NE(TypeOf(else_rhs), nullptr);
   ASSERT_NE(TypeOf(lhs), nullptr);
   ASSERT_NE(TypeOf(rhs), nullptr);
-  EXPECT_TRUE(TypeOf(stmt->condition())->Is<sem::Bool>());
+  EXPECT_TRUE(TypeOf(stmt->condition)->Is<sem::Bool>());
   EXPECT_TRUE(TypeOf(else_lhs)->UnwrapRef()->Is<sem::F32>());
   EXPECT_TRUE(TypeOf(else_rhs)->Is<sem::F32>());
   EXPECT_TRUE(TypeOf(lhs)->UnwrapRef()->Is<sem::F32>());
@@ -253,11 +253,11 @@
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 
-  ASSERT_NE(TypeOf(stmt->condition()), nullptr);
+  ASSERT_NE(TypeOf(stmt->condition), nullptr);
   ASSERT_NE(TypeOf(lhs), nullptr);
   ASSERT_NE(TypeOf(rhs), nullptr);
 
-  EXPECT_TRUE(TypeOf(stmt->condition())->Is<sem::I32>());
+  EXPECT_TRUE(TypeOf(stmt->condition)->Is<sem::I32>());
   EXPECT_TRUE(TypeOf(lhs)->UnwrapRef()->Is<sem::F32>());
   EXPECT_TRUE(TypeOf(rhs)->Is<sem::F32>());
   EXPECT_EQ(BlockOf(lhs), case_block);
@@ -282,7 +282,7 @@
 
 TEST_F(ResolverTest, Stmt_VariableDecl) {
   auto* var = Var("my_var", ty.i32(), ast::StorageClass::kNone, Expr(2));
-  auto* init = var->constructor();
+  auto* init = var->constructor;
 
   auto* decl = Decl(var);
   WrapInFunction(decl);
@@ -296,7 +296,7 @@
 TEST_F(ResolverTest, Stmt_VariableDecl_Alias) {
   auto* my_int = Alias("MyInt", ty.i32());
   auto* var = Var("my_var", ty.Of(my_int), ast::StorageClass::kNone, Expr(2));
-  auto* init = var->constructor();
+  auto* init = var->constructor;
 
   auto* decl = Decl(var);
   WrapInFunction(decl);
@@ -343,24 +343,24 @@
 
   // Declare i32 "foo" inside a block
   auto* foo_i32 = Var("foo", ty.i32(), ast::StorageClass::kNone, Expr(2));
-  auto* foo_i32_init = foo_i32->constructor();
+  auto* foo_i32_init = foo_i32->constructor;
   auto* foo_i32_decl = Decl(foo_i32);
 
   // Reference "foo" inside the block
   auto* bar_i32 = Var("bar", ty.i32(), ast::StorageClass::kNone, Expr("foo"));
-  auto* bar_i32_init = bar_i32->constructor();
+  auto* bar_i32_init = bar_i32->constructor;
   auto* bar_i32_decl = Decl(bar_i32);
 
   auto* inner = Block(foo_i32_decl, bar_i32_decl);
 
   // Declare f32 "foo" at function scope
   auto* foo_f32 = Var("foo", ty.f32(), ast::StorageClass::kNone, Expr(2.f));
-  auto* foo_f32_init = foo_f32->constructor();
+  auto* foo_f32_init = foo_f32->constructor;
   auto* foo_f32_decl = Decl(foo_f32);
 
   // Reference "foo" at function scope
   auto* bar_f32 = Var("bar", ty.f32(), ast::StorageClass::kNone, Expr("foo"));
-  auto* bar_f32_init = bar_f32->constructor();
+  auto* bar_f32_init = bar_f32->constructor;
   auto* bar_f32_decl = Decl(bar_f32);
 
   Func("func", params, ty.void_(), {inner, foo_f32_decl, bar_f32_decl},
@@ -379,12 +379,12 @@
   EXPECT_EQ(StmtOf(bar_i32_init), bar_i32_decl);
   EXPECT_EQ(StmtOf(foo_f32_init), foo_f32_decl);
   EXPECT_EQ(StmtOf(bar_f32_init), bar_f32_decl);
-  EXPECT_TRUE(CheckVarUsers(foo_i32, {bar_i32->constructor()}));
-  EXPECT_TRUE(CheckVarUsers(foo_f32, {bar_f32->constructor()}));
-  ASSERT_NE(VarOf(bar_i32->constructor()), nullptr);
-  EXPECT_EQ(VarOf(bar_i32->constructor())->Declaration(), foo_i32);
-  ASSERT_NE(VarOf(bar_f32->constructor()), nullptr);
-  EXPECT_EQ(VarOf(bar_f32->constructor())->Declaration(), foo_f32);
+  EXPECT_TRUE(CheckVarUsers(foo_i32, {bar_i32->constructor}));
+  EXPECT_TRUE(CheckVarUsers(foo_f32, {bar_f32->constructor}));
+  ASSERT_NE(VarOf(bar_i32->constructor), nullptr);
+  EXPECT_EQ(VarOf(bar_i32->constructor)->Declaration(), foo_i32);
+  ASSERT_NE(VarOf(bar_f32->constructor), nullptr);
+  EXPECT_EQ(VarOf(bar_f32->constructor)->Declaration(), foo_f32);
 }
 
 TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScopeAfterFunctionScope) {
@@ -400,18 +400,18 @@
 
   // Declare i32 "foo" inside a function
   auto* fn_i32 = Var("foo", ty.i32(), ast::StorageClass::kNone, Expr(2));
-  auto* fn_i32_init = fn_i32->constructor();
+  auto* fn_i32_init = fn_i32->constructor;
   auto* fn_i32_decl = Decl(fn_i32);
   Func("func_i32", params, ty.void_(), {fn_i32_decl}, ast::DecorationList{});
 
   // Declare f32 "foo" at module scope
   auto* mod_f32 = Var("foo", ty.f32(), ast::StorageClass::kPrivate, Expr(2.f));
-  auto* mod_init = mod_f32->constructor();
+  auto* mod_init = mod_f32->constructor;
   AST().AddGlobalVariable(mod_f32);
 
   // Reference "foo" in another function
   auto* fn_f32 = Var("bar", ty.f32(), ast::StorageClass::kNone, Expr("foo"));
-  auto* fn_f32_init = fn_f32->constructor();
+  auto* fn_f32_init = fn_f32->constructor;
   auto* fn_f32_decl = Decl(fn_f32);
   Func("func_f32", params, ty.void_(), {fn_f32_decl}, ast::DecorationList{});
 
@@ -426,9 +426,9 @@
   EXPECT_EQ(StmtOf(mod_init), nullptr);
   EXPECT_EQ(StmtOf(fn_f32_init), fn_f32_decl);
   EXPECT_TRUE(CheckVarUsers(fn_i32, {}));
-  EXPECT_TRUE(CheckVarUsers(mod_f32, {fn_f32->constructor()}));
-  ASSERT_NE(VarOf(fn_f32->constructor()), nullptr);
-  EXPECT_EQ(VarOf(fn_f32->constructor())->Declaration(), mod_f32);
+  EXPECT_TRUE(CheckVarUsers(mod_f32, {fn_f32->constructor}));
+  ASSERT_NE(VarOf(fn_f32->constructor), nullptr);
+  EXPECT_EQ(VarOf(fn_f32->constructor)->Declaration(), mod_f32);
 }
 
 TEST_F(ResolverTest, ArraySize_UnsignedLiteral) {
@@ -1115,7 +1115,7 @@
   ASSERT_NE(sma, nullptr);
   EXPECT_TRUE(sma->Member()->Type()->Is<sem::F32>());
   EXPECT_EQ(sma->Member()->Index(), 1u);
-  EXPECT_EQ(sma->Member()->Declaration()->symbol(),
+  EXPECT_EQ(sma->Member()->Declaration()->symbol,
             Symbols().Get("second_member"));
 }
 
@@ -1623,7 +1623,7 @@
   ASSERT_EQ(r()->error(),
             "12:34 error: Binary expression operand types are invalid for "
             "this operation: " +
-                FriendlyName(lhs_type) + " " + ast::FriendlyName(expr->op()) +
+                FriendlyName(lhs_type) + " " + ast::FriendlyName(expr->op) +
                 " " + FriendlyName(rhs_type));
 }
 INSTANTIATE_TEST_SUITE_P(
@@ -1672,7 +1672,7 @@
     ASSERT_EQ(r()->error(),
               "12:34 error: Binary expression operand types are invalid for "
               "this operation: " +
-                  FriendlyName(lhs_type) + " " + ast::FriendlyName(expr->op()) +
+                  FriendlyName(lhs_type) + " " + ast::FriendlyName(expr->op) +
                   " " + FriendlyName(rhs_type));
   }
 }
@@ -1714,7 +1714,7 @@
     ASSERT_EQ(r()->error(),
               "12:34 error: Binary expression operand types are invalid for "
               "this operation: " +
-                  FriendlyName(lhs_type) + " " + ast::FriendlyName(expr->op()) +
+                  FriendlyName(lhs_type) + " " + ast::FriendlyName(expr->op) +
                   " " + FriendlyName(rhs_type));
   }
 }
diff --git a/src/resolver/validation_test.cc b/src/resolver/validation_test.cc
index 8a1511f..3871e59 100644
--- a/src/resolver/validation_test.cc
+++ b/src/resolver/validation_test.cc
@@ -49,13 +49,13 @@
 
 class FakeStmt : public Castable<FakeStmt, ast::Statement> {
  public:
-  FakeStmt(ProgramID program_id, Source source) : Base(program_id, source) {}
+  FakeStmt(ProgramID pid, Source src) : Base(pid, src) {}
   FakeStmt* Clone(CloneContext*) const override { return nullptr; }
 };
 
 class FakeExpr : public Castable<FakeExpr, ast::Expression> {
  public:
-  FakeExpr(ProgramID program_id, Source source) : Base(program_id, source) {}
+  FakeExpr(ProgramID pid, Source src) : Base(pid, src) {}
   FakeExpr* Clone(CloneContext*) const override { return nullptr; }
 };
 
diff --git a/src/scope_stack_test.cc b/src/scope_stack_test.cc
index 85bd86b..9c6c0a5 100644
--- a/src/scope_stack_test.cc
+++ b/src/scope_stack_test.cc
@@ -34,11 +34,11 @@
 TEST_F(ScopeStackTest, Global_SetWithPointer) {
   auto* v = Var("my_var", ty.f32(), ast::StorageClass::kNone);
   ScopeStack<ast::Variable*> s;
-  s.set_global(v->symbol(), v);
+  s.set_global(v->symbol, v);
 
   ast::Variable* v2 = nullptr;
-  EXPECT_TRUE(s.get(v->symbol(), &v2));
-  EXPECT_EQ(v2->symbol(), v->symbol());
+  EXPECT_TRUE(s.get(v->symbol, &v2));
+  EXPECT_EQ(v2->symbol, v->symbol);
 }
 
 TEST_F(ScopeStackTest, Global_CanNotPop) {
diff --git a/src/sem/block_statement.cc b/src/sem/block_statement.cc
index 70cdd0b..8022cff 100644
--- a/src/sem/block_statement.cc
+++ b/src/sem/block_statement.cc
@@ -40,7 +40,7 @@
 }
 
 FunctionBlockStatement::FunctionBlockStatement(const ast::Function* function)
-    : Base(function->body(), nullptr), function_(function) {}
+    : Base(function->body, nullptr), function_(function) {}
 
 FunctionBlockStatement::~FunctionBlockStatement() = default;
 
diff --git a/src/sem/function.cc b/src/sem/function.cc
index 4912a69..0743cb4 100644
--- a/src/sem/function.cc
+++ b/src/sem/function.cc
@@ -57,7 +57,7 @@
   std::vector<std::pair<const Variable*, ast::LocationDecoration*>> ret;
 
   for (auto* var : ReferencedModuleVariables()) {
-    for (auto* deco : var->Declaration()->decorations()) {
+    for (auto* deco : var->Declaration()->decorations) {
       if (auto* location = deco->As<ast::LocationDecoration>()) {
         ret.push_back({var, location});
         break;
@@ -75,7 +75,7 @@
       continue;
     }
 
-    if (auto binding_point = var->Declaration()->binding_point()) {
+    if (auto binding_point = var->Declaration()->BindingPoint()) {
       ret.push_back({var, binding_point});
     }
   }
@@ -90,7 +90,7 @@
       continue;
     }
 
-    if (auto binding_point = var->Declaration()->binding_point()) {
+    if (auto binding_point = var->Declaration()->BindingPoint()) {
       ret.push_back({var, binding_point});
     }
   }
@@ -102,7 +102,7 @@
   std::vector<std::pair<const Variable*, ast::BuiltinDecoration*>> ret;
 
   for (auto* var : ReferencedModuleVariables()) {
-    for (auto* deco : var->Declaration()->decorations()) {
+    for (auto* deco : var->Declaration()->decorations) {
       if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
         ret.push_back({var, builtin});
         break;
@@ -136,7 +136,7 @@
   for (auto* var : ReferencedModuleVariables()) {
     auto* unwrapped_type = var->Type()->UnwrapRef();
     if (unwrapped_type->TypeInfo().Is(type_info)) {
-      if (auto binding_point = var->Declaration()->binding_point()) {
+      if (auto binding_point = var->Declaration()->BindingPoint()) {
         ret.push_back({var, binding_point});
       }
     }
@@ -164,7 +164,7 @@
       continue;
     }
 
-    if (auto binding_point = var->Declaration()->binding_point()) {
+    if (auto binding_point = var->Declaration()->BindingPoint()) {
       ret.push_back({var, binding_point});
     }
   }
@@ -189,7 +189,7 @@
       continue;
     }
 
-    if (auto binding_point = var->Declaration()->binding_point()) {
+    if (auto binding_point = var->Declaration()->BindingPoint()) {
       ret.push_back({var, binding_point});
     }
   }
diff --git a/src/sem/function.h b/src/sem/function.h
index 08ea5bf..cd0c014 100644
--- a/src/sem/function.h
+++ b/src/sem/function.h
@@ -52,9 +52,9 @@
 /// Function holds the semantic information for function nodes.
 class Function : public Castable<Function, CallTarget> {
  public:
-  /// A vector of [Variable*, ast::Variable::BindingPoint] pairs
+  /// A vector of [Variable*, ast::VariableBindingPoint] pairs
   using VariableBindings =
-      std::vector<std::pair<const Variable*, ast::Variable::BindingPoint>>;
+      std::vector<std::pair<const Variable*, ast::VariableBindingPoint>>;
 
   /// Constructor
   /// @param declaration the ast::Function
diff --git a/src/sem/sem_struct_test.cc b/src/sem/sem_struct_test.cc
index ed0eba3..104df11 100644
--- a/src/sem/sem_struct_test.cc
+++ b/src/sem/sem_struct_test.cc
@@ -28,7 +28,7 @@
       create<ast::Struct>(name, ast::StructMemberList{}, ast::DecorationList{});
   auto* ptr = impl;
   auto* s =
-      create<sem::Struct>(impl, impl->name(), StructMemberList{}, 4 /* align */,
+      create<sem::Struct>(impl, impl->name, StructMemberList{}, 4 /* align */,
                           8 /* size */, 16 /* size_no_padding */);
   EXPECT_EQ(s->Declaration(), ptr);
   EXPECT_EQ(s->Align(), 4u);
@@ -41,7 +41,7 @@
   auto* impl =
       create<ast::Struct>(name, ast::StructMemberList{}, ast::DecorationList{});
   auto* s =
-      create<sem::Struct>(impl, impl->name(), StructMemberList{}, 4 /* align */,
+      create<sem::Struct>(impl, impl->name, StructMemberList{}, 4 /* align */,
                           4 /* size */, 4 /* size_no_padding */);
   EXPECT_EQ(s->type_name(), "__struct_$1");
 }
@@ -51,7 +51,7 @@
   auto* impl =
       create<ast::Struct>(name, ast::StructMemberList{}, ast::DecorationList{});
   auto* s =
-      create<sem::Struct>(impl, impl->name(), StructMemberList{}, 4 /* align */,
+      create<sem::Struct>(impl, impl->name, StructMemberList{}, 4 /* align */,
                           4 /* size */, 4 /* size_no_padding */);
   EXPECT_EQ(s->FriendlyName(Symbols()), "my_struct");
 }
diff --git a/src/sem/struct.cc b/src/sem/struct.cc
index dea2fd1..9238ec9 100644
--- a/src/sem/struct.cc
+++ b/src/sem/struct.cc
@@ -51,7 +51,7 @@
 
 const StructMember* Struct::FindMember(Symbol name) const {
   for (auto* member : members_) {
-    if (member->Declaration()->symbol() == name) {
+    if (member->Declaration()->symbol == name) {
       return member;
     }
   }
diff --git a/src/transform/array_length_from_uniform.cc b/src/transform/array_length_from_uniform.cc
index 0a2f3ec..70ba5fc 100644
--- a/src/transform/array_length_from_uniform.cc
+++ b/src/transform/array_length_from_uniform.cc
@@ -106,21 +106,21 @@
     // We assume that the argument to `arrayLength` has the form
     // `&resource.array`, which requires that `InlinePointerLets` and
     // `Simplify` have been run before this transform.
-    auto* param = call_expr->args()[0]->As<ast::UnaryOpExpression>();
-    if (!param || param->op() != ast::UnaryOp::kAddressOf) {
+    auto* param = call_expr->args[0]->As<ast::UnaryOpExpression>();
+    if (!param || param->op != ast::UnaryOp::kAddressOf) {
       TINT_ICE(Transform, ctx.dst->Diagnostics())
           << "expected form of arrayLength argument to be "
              "&resource.array";
       break;
     }
-    auto* accessor = param->expr()->As<ast::MemberAccessorExpression>();
+    auto* accessor = param->expr->As<ast::MemberAccessorExpression>();
     if (!accessor) {
       TINT_ICE(Transform, ctx.dst->Diagnostics())
           << "expected form of arrayLength argument to be "
              "&resource.array";
       break;
     }
-    auto* storage_buffer_expr = accessor->structure();
+    auto* storage_buffer_expr = accessor->structure;
     auto* storage_buffer_sem =
         sem.Get(storage_buffer_expr)->As<sem::VariableUser>();
     if (!storage_buffer_sem) {
@@ -151,7 +151,7 @@
     // Load the total storage buffer size from the UBO.
     uint32_t array_index = idx_itr->second / 4;
     auto* vec_expr = ctx.dst->IndexAccessor(
-        ctx.dst->MemberAccessor(get_ubo()->symbol(), kBufferSizeMemberName),
+        ctx.dst->MemberAccessor(get_ubo()->symbol, kBufferSizeMemberName),
         array_index);
     uint32_t vec_index = idx_itr->second % 4;
     auto* total_storage_buffer_size =
diff --git a/src/transform/binding_remapper.cc b/src/transform/binding_remapper.cc
index adecc84..3fe4e6e 100644
--- a/src/transform/binding_remapper.cc
+++ b/src/transform/binding_remapper.cc
@@ -65,9 +65,9 @@
       auto* func = ctx.src->Sem().Get(func_ast);
       std::unordered_map<sem::BindingPoint, int> binding_point_counts;
       for (auto* var : func->ReferencedModuleVariables()) {
-        if (auto binding_point = var->Declaration()->binding_point()) {
-          BindingPoint from{binding_point.group->value(),
-                            binding_point.binding->value()};
+        if (auto binding_point = var->Declaration()->BindingPoint()) {
+          BindingPoint from{binding_point.group->value,
+                            binding_point.binding->value};
           auto bp_it = remappings->binding_points.find(from);
           if (bp_it != remappings->binding_points.end()) {
             // Remapped
@@ -87,17 +87,17 @@
   }
 
   for (auto* var : ctx.src->AST().GlobalVariables()) {
-    if (auto binding_point = var->binding_point()) {
+    if (auto binding_point = var->BindingPoint()) {
       // The original binding point
-      BindingPoint from{binding_point.group->value(),
-                        binding_point.binding->value()};
+      BindingPoint from{binding_point.group->value,
+                        binding_point.binding->value};
 
       // The binding point after remapping
       BindingPoint bp = from;
 
       // Replace any group or binding decorations.
       // Note: This has to be performed *before* remapping access controls, as
-      // `ctx.Clone(var->decorations())` depend on these replacements.
+      // `ctx.Clone(var->decorations)` depend on these replacements.
       auto bp_it = remappings->binding_points.find(from);
       if (bp_it != remappings->binding_points.end()) {
         BindingPoint to = bp_it->second;
@@ -125,15 +125,15 @@
           ctx.dst->Diagnostics().add_error(
               diag::System::Transform,
               "cannot apply access control to variable with storage class " +
-                  std::string(ast::str(sem->StorageClass())));
+                  std::string(ast::ToString(sem->StorageClass())));
           return;
         }
         auto* ty = sem->Type()->UnwrapRef();
         ast::Type* inner_ty = CreateASTTypeFor(ctx, ty);
         auto* new_var = ctx.dst->create<ast::Variable>(
-            ctx.Clone(var->source()), ctx.Clone(var->symbol()),
-            var->declared_storage_class(), ac, inner_ty, var->is_const(),
-            ctx.Clone(var->constructor()), ctx.Clone(var->decorations()));
+            ctx.Clone(var->source), ctx.Clone(var->symbol),
+            var->declared_storage_class, ac, inner_ty, var->is_const,
+            ctx.Clone(var->constructor), ctx.Clone(var->decorations));
         ctx.Replace(var, new_var);
       }
 
@@ -142,7 +142,7 @@
         auto* decoration =
             ctx.dst->ASTNodes().Create<ast::DisableValidationDecoration>(
                 ctx.dst->ID(), ast::DisabledValidation::kBindingPointCollision);
-        ctx.InsertBefore(var->decorations(), *var->decorations().begin(),
+        ctx.InsertBefore(var->decorations, *var->decorations.begin(),
                          decoration);
       }
     }
diff --git a/src/transform/calculate_array_length.cc b/src/transform/calculate_array_length.cc
index b4d1e12..37394a0 100644
--- a/src/transform/calculate_array_length.cc
+++ b/src/transform/calculate_array_length.cc
@@ -54,9 +54,8 @@
 
 }  // namespace
 
-CalculateArrayLength::BufferSizeIntrinsic::BufferSizeIntrinsic(
-    ProgramID program_id)
-    : Base(program_id) {}
+CalculateArrayLength::BufferSizeIntrinsic::BufferSizeIntrinsic(ProgramID pid)
+    : Base(pid) {}
 CalculateArrayLength::BufferSizeIntrinsic::~BufferSizeIntrinsic() = default;
 std::string CalculateArrayLength::BufferSizeIntrinsic::InternalName() const {
   return "intrinsic_buffer_size";
@@ -82,7 +81,7 @@
     return utils::GetOrCreate(buffer_size_intrinsics, buffer_type, [&] {
       auto name = ctx.dst->Sym();
       auto* buffer_typename =
-          ctx.dst->ty.type_name(ctx.Clone(buffer_type->Declaration()->name()));
+          ctx.dst->ty.type_name(ctx.Clone(buffer_type->Declaration()->name));
       auto* disable_validation =
           ctx.dst->ASTNodes().Create<ast::DisableValidationDecoration>(
               ctx.dst->ID(),
@@ -134,14 +133,14 @@
           // We can assume that the arrayLength() call has a single argument of
           // the form: arrayLength(&X.Y) where X is an expression that resolves
           // to the storage buffer structure, and Y is the runtime sized array.
-          auto* arg = call_expr->args()[0];
+          auto* arg = call_expr->args[0];
           auto* address_of = arg->As<ast::UnaryOpExpression>();
-          if (!address_of || address_of->op() != ast::UnaryOp::kAddressOf) {
+          if (!address_of || address_of->op != ast::UnaryOp::kAddressOf) {
             TINT_ICE(Transform, ctx.dst->Diagnostics())
                 << "arrayLength() expected pointer to member access, got "
                 << address_of->TypeInfo().name;
           }
-          auto* array_expr = address_of->expr();
+          auto* array_expr = address_of->expr;
 
           auto* accessor = array_expr->As<ast::MemberAccessorExpression>();
           if (!accessor) {
@@ -151,7 +150,7 @@
                 << array_expr->TypeInfo().name;
             break;
           }
-          auto* storage_buffer_expr = accessor->structure();
+          auto* storage_buffer_expr = accessor->structure;
           auto* storage_buffer_sem = sem.Get(storage_buffer_expr);
           auto* storage_buffer_type =
               storage_buffer_sem->Type()->UnwrapRef()->As<sem::Struct>();
@@ -201,7 +200,7 @@
                         //  X.GetDimensions(ARGS..) by the writer
                         buffer_size, ctx.Clone(storage_buffer_expr),
                         ctx.dst->AddressOf(ctx.dst->Expr(
-                            buffer_size_result->variable()->symbol()))));
+                            buffer_size_result->variable->symbol))));
 
                 // Calculate actual array length
                 //                total_storage_buffer_size - array_offset
@@ -213,16 +212,16 @@
                 auto* array_length_var = ctx.dst->Decl(ctx.dst->Const(
                     name, ctx.dst->ty.u32(),
                     ctx.dst->Div(
-                        ctx.dst->Sub(buffer_size_result->variable()->symbol(),
+                        ctx.dst->Sub(buffer_size_result->variable->symbol,
                                      array_offset),
                         array_stride)));
 
                 // Insert the array length calculations at the top of the block
-                ctx.InsertBefore(block->statements(), *block->begin(),
+                ctx.InsertBefore(block->statements, block->statements[0],
                                  buffer_size_result);
-                ctx.InsertBefore(block->statements(), *block->begin(),
+                ctx.InsertBefore(block->statements, block->statements[0],
                                  call_get_dims);
-                ctx.InsertBefore(block->statements(), *block->begin(),
+                ctx.InsertBefore(block->statements, block->statements[0],
                                  array_length_var);
                 return name;
               });
diff --git a/src/transform/canonicalize_entry_point_io.cc b/src/transform/canonicalize_entry_point_io.cc
index 46f24ae..28378b1 100644
--- a/src/transform/canonicalize_entry_point_io.cc
+++ b/src/transform/canonicalize_entry_point_io.cc
@@ -40,24 +40,24 @@
 // those with builtin attributes.
 bool StructMemberComparator(const ast::StructMember* a,
                             const ast::StructMember* b) {
-  auto* a_loc = ast::GetDecoration<ast::LocationDecoration>(a->decorations());
-  auto* b_loc = ast::GetDecoration<ast::LocationDecoration>(b->decorations());
-  auto* a_blt = ast::GetDecoration<ast::BuiltinDecoration>(a->decorations());
-  auto* b_blt = ast::GetDecoration<ast::BuiltinDecoration>(b->decorations());
+  auto* a_loc = ast::GetDecoration<ast::LocationDecoration>(a->decorations);
+  auto* b_loc = ast::GetDecoration<ast::LocationDecoration>(b->decorations);
+  auto* a_blt = ast::GetDecoration<ast::BuiltinDecoration>(a->decorations);
+  auto* b_blt = ast::GetDecoration<ast::BuiltinDecoration>(b->decorations);
   if (a_loc) {
     if (!b_loc) {
       // `a` has location attribute and `b` does not: `a` goes first.
       return true;
     }
     // Both have location attributes: smallest goes first.
-    return a_loc->value() < b_loc->value();
+    return a_loc->value < b_loc->value;
   } else {
     if (b_loc) {
       // `b` has location attribute and `a` does not: `b` goes first.
       return false;
     }
     // Both are builtins: order doesn't matter, just use enum value.
-    return a_blt->value() < b_blt->value();
+    return a_blt->builtin < b_blt->builtin;
   }
 }
 
@@ -70,7 +70,7 @@
 // Returns true if `decos` contains a `sample_mask` builtin.
 bool HasSampleMask(const ast::DecorationList& decos) {
   auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(decos);
-  return builtin && builtin->value() == ast::Builtin::kSampleMask;
+  return builtin && builtin->builtin == ast::Builtin::kSampleMask;
 }
 
 }  // namespace
@@ -163,7 +163,7 @@
       // always decorated with `Flat`.
       if (type->is_integer_scalar_or_vector() &&
           ast::HasDecoration<ast::LocationDecoration>(attributes) &&
-          func_ast->pipeline_stage() == ast::PipelineStage::kFragment) {
+          func_ast->PipelineStage() == ast::PipelineStage::kFragment) {
         attributes.push_back(ctx.dst->Interpolate(
             ast::InterpolationType::kFlat, ast::InterpolationSampling::kNone));
       }
@@ -220,7 +220,7 @@
     if (cfg.shader_style == ShaderStyle::kSpirv &&
         type->is_integer_scalar_or_vector() &&
         ast::HasDecoration<ast::LocationDecoration>(attributes) &&
-        func_ast->pipeline_stage() == ast::PipelineStage::kVertex) {
+        func_ast->PipelineStage() == ast::PipelineStage::kVertex) {
       attributes.push_back(ctx.dst->Interpolate(
           ast::InterpolationType::kFlat, ast::InterpolationSampling::kNone));
     }
@@ -242,14 +242,14 @@
     // Remove the shader IO attributes from the inner function parameter, and
     // attach them to the new object instead.
     ast::DecorationList attributes;
-    for (auto* deco : param->Declaration()->decorations()) {
+    for (auto* deco : param->Declaration()->decorations) {
       if (IsShaderIODecoration(deco)) {
-        ctx.Remove(param->Declaration()->decorations(), deco);
+        ctx.Remove(param->Declaration()->decorations, deco);
         attributes.push_back(ctx.Clone(deco));
       }
     }
 
-    auto name = ctx.src->Symbols().NameFor(param->Declaration()->symbol());
+    auto name = ctx.src->Symbols().NameFor(param->Declaration()->symbol);
     auto* input_expr = AddInput(name, param->Type(), std::move(attributes));
     inner_call_parameters.push_back(input_expr);
   }
@@ -272,15 +272,15 @@
       }
 
       auto* member_ast = member->Declaration();
-      auto name = ctx.src->Symbols().NameFor(member_ast->symbol());
-      auto attributes = CloneShaderIOAttributes(member_ast->decorations());
+      auto name = ctx.src->Symbols().NameFor(member_ast->symbol);
+      auto attributes = CloneShaderIOAttributes(member_ast->decorations);
       auto* input_expr = AddInput(name, member->Type(), std::move(attributes));
       inner_struct_values.push_back(input_expr);
     }
 
     // Construct the original structure using the new shader input objects.
     inner_call_parameters.push_back(ctx.dst->Construct(
-        ctx.Clone(param->Declaration()->type()), inner_struct_values));
+        ctx.Clone(param->Declaration()->type), inner_struct_values));
   }
 
   /// Process the entry point return type.
@@ -298,8 +298,8 @@
         }
 
         auto* member_ast = member->Declaration();
-        auto name = ctx.src->Symbols().NameFor(member_ast->symbol());
-        auto attributes = CloneShaderIOAttributes(member_ast->decorations());
+        auto name = ctx.src->Symbols().NameFor(member_ast->symbol);
+        auto attributes = CloneShaderIOAttributes(member_ast->decorations);
 
         // Extract the original structure member.
         AddOutput(name, member->Type(), std::move(attributes),
@@ -307,7 +307,7 @@
       }
     } else if (!inner_ret_type->Is<sem::Void>()) {
       auto attributes =
-          CloneShaderIOAttributes(func_ast->return_type_decorations());
+          CloneShaderIOAttributes(func_ast->return_type_decorations);
 
       // Propagate the non-struct return value as is.
       AddOutput("value", func_sem->ReturnType(), std::move(attributes),
@@ -396,7 +396,7 @@
 
     // Create the output struct object, assign its members, and return it.
     auto* result_object =
-        ctx.dst->Var(wrapper_result, ctx.dst->ty.type_name(out_struct->name()));
+        ctx.dst->Var(wrapper_result, ctx.dst->ty.type_name(out_struct->name));
     wrapper_body.push_back(ctx.dst->Decl(result_object));
     wrapper_body.insert(wrapper_body.end(), assignments.begin(),
                         assignments.end());
@@ -435,31 +435,31 @@
   ast::CallExpression* CallInnerFunction() {
     // Add a suffix to the function name, as the wrapper function will take the
     // original entry point name.
-    auto ep_name = ctx.src->Symbols().NameFor(func_ast->symbol());
+    auto ep_name = ctx.src->Symbols().NameFor(func_ast->symbol);
     auto inner_name = ctx.dst->Symbols().New(ep_name + "_inner");
 
     // Clone everything, dropping the function and return type attributes.
     // The parameter attributes will have already been stripped during
     // processing.
     auto* inner_function = ctx.dst->create<ast::Function>(
-        inner_name, ctx.Clone(func_ast->params()),
-        ctx.Clone(func_ast->return_type()), ctx.Clone(func_ast->body()),
+        inner_name, ctx.Clone(func_ast->params),
+        ctx.Clone(func_ast->return_type), ctx.Clone(func_ast->body),
         ast::DecorationList{}, ast::DecorationList{});
     ctx.Replace(func_ast, inner_function);
 
     // Call the function.
-    return ctx.dst->Call(inner_function->symbol(), inner_call_parameters);
+    return ctx.dst->Call(inner_function->symbol, inner_call_parameters);
   }
 
   /// Process the entry point function.
   void Process() {
     bool needs_fixed_sample_mask = false;
     bool needs_vertex_point_size = false;
-    if (func_ast->pipeline_stage() == ast::PipelineStage::kFragment &&
+    if (func_ast->PipelineStage() == ast::PipelineStage::kFragment &&
         cfg.fixed_sample_mask != 0xFFFFFFFF) {
       needs_fixed_sample_mask = true;
     }
-    if (func_ast->pipeline_stage() == ast::PipelineStage::kVertex &&
+    if (func_ast->PipelineStage() == ast::PipelineStage::kVertex &&
         cfg.emit_vertex_point_size) {
       needs_vertex_point_size = true;
     }
@@ -506,7 +506,7 @@
 
       // Process the original return type to determine the outputs that the
       // outer function needs to produce.
-      ProcessReturnType(func_sem->ReturnType(), inner_result->symbol());
+      ProcessReturnType(func_sem->ReturnType(), inner_result->symbol);
     }
 
     // Add a fixed sample mask, if necessary.
@@ -526,17 +526,17 @@
       } else {
         auto* output_struct = CreateOutputStruct();
         wrapper_ret_type = [&, output_struct] {
-          return ctx.dst->ty.type_name(output_struct->name());
+          return ctx.dst->ty.type_name(output_struct->name);
         };
       }
     }
 
     // Create the wrapper entry point function.
     // Take the name of the original entry point function.
-    auto name = ctx.Clone(func_ast->symbol());
+    auto name = ctx.Clone(func_ast->symbol);
     auto* wrapper_func = ctx.dst->create<ast::Function>(
         name, wrapper_ep_parameters, wrapper_ret_type(),
-        ctx.dst->Block(wrapper_body), ctx.Clone(func_ast->decorations()),
+        ctx.dst->Block(wrapper_body), ctx.Clone(func_ast->decorations),
         ast::DecorationList{});
     ctx.InsertAfter(ctx.src->AST().GlobalDeclarations(), func_ast,
                     wrapper_func);
@@ -558,10 +558,10 @@
   // New structures will be created for each entry point, as necessary.
   for (auto* ty : ctx.src->AST().TypeDecls()) {
     if (auto* struct_ty = ty->As<ast::Struct>()) {
-      for (auto* member : struct_ty->members()) {
-        for (auto* deco : member->decorations()) {
+      for (auto* member : struct_ty->members) {
+        for (auto* deco : member->decorations) {
           if (IsShaderIODecoration(deco)) {
-            ctx.Remove(member->decorations(), deco);
+            ctx.Remove(member->decorations, deco);
           }
         }
       }
diff --git a/src/transform/decompose_memory_access.cc b/src/transform/decompose_memory_access.cc
index 561c29f..d6b5a40 100644
--- a/src/transform/decompose_memory_access.cc
+++ b/src/transform/decompose_memory_access.cc
@@ -332,11 +332,11 @@
   /// @returns an Offset for the given ast::Expression
   const Offset* ToOffset(ast::Expression* expr) {
     if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) {
-      if (auto* u32 = scalar->literal()->As<ast::UintLiteral>()) {
-        return offsets_.Create<OffsetLiteral>(u32->value());
-      } else if (auto* i32 = scalar->literal()->As<ast::SintLiteral>()) {
-        if (i32->value() > 0) {
-          return offsets_.Create<OffsetLiteral>(i32->value());
+      if (auto* u32 = scalar->literal->As<ast::UintLiteral>()) {
+        return offsets_.Create<OffsetLiteral>(u32->value);
+      } else if (auto* i32 = scalar->literal->As<ast::SintLiteral>()) {
+        if (i32->value > 0) {
+          return offsets_.Create<OffsetLiteral>(i32->value);
         }
       }
     }
@@ -625,7 +625,7 @@
               for (auto* member : str->Members()) {
                 auto* offset = b.Add("offset", member->Offset());
                 auto* access = b.MemberAccessor(
-                    "value", ctx.Clone(member->Declaration()->symbol()));
+                    "value", ctx.Clone(member->Declaration()->symbol));
                 Symbol store =
                     StoreFunc(buf_ty, member->Type()->UnwrapRef(), var_user);
                 auto* call = b.Call(store, "buffer", offset, access);
@@ -697,16 +697,16 @@
           ast::DecorationList{});
 
       b.AST().AddFunction(func);
-      return func->symbol();
+      return func->symbol;
     });
   }
 };
 
-DecomposeMemoryAccess::Intrinsic::Intrinsic(ProgramID program_id,
+DecomposeMemoryAccess::Intrinsic::Intrinsic(ProgramID pid,
                                             Op o,
                                             ast::StorageClass sc,
                                             DataType ty)
-    : Base(program_id), op(o), storage_class(sc), type(ty) {}
+    : Base(pid), op(o), storage_class(sc), type(ty) {}
 DecomposeMemoryAccess::Intrinsic::~Intrinsic() = default;
 std::string DecomposeMemoryAccess::Intrinsic::InternalName() const {
   std::stringstream ss;
@@ -837,7 +837,7 @@
       auto* accessor_sem = sem.Get(accessor);
       if (auto* swizzle = accessor_sem->As<sem::Swizzle>()) {
         if (swizzle->Indices().size() == 1) {
-          if (auto access = state.TakeAccess(accessor->structure())) {
+          if (auto access = state.TakeAccess(accessor->structure)) {
             auto* vec_ty = access.type->As<sem::Vector>();
             auto* offset =
                 state.Mul(vec_ty->type()->Size(), swizzle->Indices()[0]);
@@ -849,9 +849,9 @@
           }
         }
       } else {
-        if (auto access = state.TakeAccess(accessor->structure())) {
+        if (auto access = state.TakeAccess(accessor->structure)) {
           auto* str_ty = access.type->As<sem::Struct>();
-          auto* member = str_ty->FindMember(accessor->member()->symbol());
+          auto* member = str_ty->FindMember(accessor->member->symbol);
           auto offset = member->Offset();
           state.AddAccess(accessor, {
                                         access.var,
@@ -864,10 +864,10 @@
     }
 
     if (auto* accessor = node->As<ast::ArrayAccessorExpression>()) {
-      if (auto access = state.TakeAccess(accessor->array())) {
+      if (auto access = state.TakeAccess(accessor->array)) {
         // X[Y]
         if (auto* arr = access.type->As<sem::Array>()) {
-          auto* offset = state.Mul(arr->Stride(), accessor->idx_expr());
+          auto* offset = state.Mul(arr->Stride(), accessor->index);
           state.AddAccess(accessor, {
                                         access.var,
                                         state.Add(access.offset, offset),
@@ -876,8 +876,7 @@
           continue;
         }
         if (auto* vec_ty = access.type->As<sem::Vector>()) {
-          auto* offset =
-              state.Mul(vec_ty->type()->Size(), accessor->idx_expr());
+          auto* offset = state.Mul(vec_ty->type()->Size(), accessor->index);
           state.AddAccess(accessor, {
                                         access.var,
                                         state.Add(access.offset, offset),
@@ -886,8 +885,7 @@
           continue;
         }
         if (auto* mat_ty = access.type->As<sem::Matrix>()) {
-          auto* offset =
-              state.Mul(mat_ty->ColumnStride(), accessor->idx_expr());
+          auto* offset = state.Mul(mat_ty->ColumnStride(), accessor->index);
           state.AddAccess(accessor, {
                                         access.var,
                                         state.Add(access.offset, offset),
@@ -899,9 +897,9 @@
     }
 
     if (auto* op = node->As<ast::UnaryOpExpression>()) {
-      if (op->op() == ast::UnaryOp::kAddressOf) {
+      if (op->op == ast::UnaryOp::kAddressOf) {
         // &X
-        if (auto access = state.TakeAccess(op->expr())) {
+        if (auto access = state.TakeAccess(op->expr)) {
           // HLSL does not support pointers, so just take the access from the
           // reference and place it on the pointer.
           state.AddAccess(op, access);
@@ -913,7 +911,7 @@
     if (auto* assign = node->As<ast::AssignmentStatement>()) {
       // X = Y
       // Move the LHS access to a store.
-      if (auto lhs = state.TakeAccess(assign->lhs())) {
+      if (auto lhs = state.TakeAccess(assign->lhs)) {
         state.stores.emplace_back(Store{assign, lhs});
       }
     }
@@ -927,8 +925,8 @@
           // may refer to a structure holding a runtime array, which cannot be
           // loaded. Instead replace X with the underlying storage / uniform
           // buffer variable.
-          if (auto access = state.TakeAccess(call_expr->args()[0])) {
-            ctx.Replace(call_expr->args()[0], [=, &ctx] {
+          if (auto access = state.TakeAccess(call_expr->args[0])) {
+            ctx.Replace(call_expr->args[0], [=, &ctx] {
               return ctx.CloneWithoutTransform(access.var->Declaration());
             });
           }
@@ -938,11 +936,11 @@
           // arrayLength(X)
           // Don't convert X into a load, this intrinsic actually requires the
           // real pointer.
-          state.TakeAccess(call_expr->args()[0]);
+          state.TakeAccess(call_expr->args[0]);
           continue;
         }
         if (intrinsic->IsAtomic()) {
-          if (auto access = state.TakeAccess(call_expr->args()[0])) {
+          if (auto access = state.TakeAccess(call_expr->args[0])) {
             // atomic___(X)
             ctx.Replace(call_expr, [=, &ctx, &state] {
               auto* buf = access.var->Declaration();
@@ -954,8 +952,8 @@
                                    access.var->As<sem::VariableUser>());
 
               ast::ExpressionList args{ctx.Clone(buf), offset};
-              for (size_t i = 1; i < call_expr->args().size(); i++) {
-                auto* arg = call_expr->args()[i];
+              for (size_t i = 1; i < call_expr->args.size(); i++) {
+                auto* arg = call_expr->args[i];
                 args.emplace_back(ctx.Clone(arg));
               }
               return ctx.dst->Call(func, args);
@@ -992,7 +990,7 @@
       auto* offset = store.target.offset->Build(ctx);
       auto* buf_ty = store.target.var->Type()->UnwrapRef();
       auto* el_ty = store.target.type->UnwrapRef();
-      auto* value = store.assignment->rhs();
+      auto* value = store.assignment->rhs;
       Symbol func = state.StoreFunc(buf_ty, el_ty,
                                     store.target.var->As<sem::VariableUser>());
       auto* call = ctx.dst->Call(func, ctx.CloneWithoutTransform(buf), offset,
diff --git a/src/transform/decompose_strided_matrix.cc b/src/transform/decompose_strided_matrix.cc
index 786f509..497a891 100644
--- a/src/transform/decompose_strided_matrix.cc
+++ b/src/transform/decompose_strided_matrix.cc
@@ -86,11 +86,11 @@
           continue;
         }
         auto* deco = ast::GetDecoration<ast::StrideDecoration>(
-            member->Declaration()->decorations());
+            member->Declaration()->decorations);
         if (!deco) {
           continue;
         }
-        uint32_t stride = deco->stride();
+        uint32_t stride = deco->stride;
         if (matrix->ColumnStride() == stride) {
           continue;
         }
@@ -147,11 +147,11 @@
   ctx.ReplaceAll(
       [&](ast::ArrayAccessorExpression* expr) -> ast::ArrayAccessorExpression* {
         if (auto* access =
-                ctx.src->Sem().Get<sem::StructMemberAccess>(expr->array())) {
+                ctx.src->Sem().Get<sem::StructMemberAccess>(expr->array)) {
           auto it = decomposed.find(access->Member()->Declaration());
           if (it != decomposed.end()) {
-            auto* obj = ctx.CloneWithoutTransform(expr->array());
-            auto* idx = ctx.Clone(expr->idx_expr());
+            auto* obj = ctx.CloneWithoutTransform(expr->array);
+            auto* idx = ctx.Clone(expr->index);
             return ctx.dst->IndexAccessor(obj, idx);
           }
         }
@@ -165,8 +165,7 @@
   //   ssbo.mat = mat_to_arr(m)
   std::unordered_map<MatrixInfo, Symbol, MatrixInfo::Hasher> mat_to_arr;
   ctx.ReplaceAll([&](ast::AssignmentStatement* stmt) -> ast::Statement* {
-    if (auto* access =
-            ctx.src->Sem().Get<sem::StructMemberAccess>(stmt->lhs())) {
+    if (auto* access = ctx.src->Sem().Get<sem::StructMemberAccess>(stmt->lhs)) {
       auto it = decomposed.find(access->Member()->Declaration());
       if (it == decomposed.end()) {
         return nullptr;
@@ -196,8 +195,8 @@
                       });
         return name;
       });
-      auto* lhs = ctx.CloneWithoutTransform(stmt->lhs());
-      auto* rhs = ctx.dst->Call(fn, ctx.Clone(stmt->rhs()));
+      auto* lhs = ctx.CloneWithoutTransform(stmt->lhs);
+      auto* rhs = ctx.dst->Call(fn, ctx.Clone(stmt->rhs));
       return ctx.dst->Assign(lhs, rhs);
     }
     return nullptr;
diff --git a/src/transform/external_texture_transform.cc b/src/transform/external_texture_transform.cc
index da2539a..3b540ad 100644
--- a/src/transform/external_texture_transform.cc
+++ b/src/transform/external_texture_transform.cc
@@ -53,43 +53,43 @@
           // When a textureLoad or textureSampleLevel has been identified, check
           // if the first parameter is an external texture.
           if (auto* var =
-                  sem.Get(call_expr->args()[0])->As<sem::VariableUser>()) {
+                  sem.Get(call_expr->args[0])->As<sem::VariableUser>()) {
             if (var->Variable()
                     ->Type()
                     ->UnwrapRef()
                     ->Is<sem::ExternalTexture>()) {
               if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad &&
-                  call_expr->args().size() != 2) {
+                  call_expr->args.size() != 2) {
                 TINT_ICE(Transform, ctx.dst->Diagnostics())
                     << "expected textureLoad call with a texture_external to "
                        "have 2 parameters, found "
-                    << call_expr->args().size() << " parameters";
+                    << call_expr->args.size() << " parameters";
               }
 
               if (intrinsic->Type() ==
                       sem::IntrinsicType::kTextureSampleLevel &&
-                  call_expr->args().size() != 3) {
+                  call_expr->args.size() != 3) {
                 TINT_ICE(Transform, ctx.dst->Diagnostics())
                     << "expected textureSampleLevel call with a "
                        "texture_external to have 3 parameters, found "
-                    << call_expr->args().size() << " parameters";
+                    << call_expr->args.size() << " parameters";
               }
 
               // Replace the call with another that has the same parameters in
               // addition to a level parameter (always zero for external
               // textures).
-              auto* exp = ctx.Clone(call_expr->func());
-              auto* externalTextureParam = ctx.Clone(call_expr->args()[0]);
+              auto* exp = ctx.Clone(call_expr->func);
+              auto* externalTextureParam = ctx.Clone(call_expr->args[0]);
 
               ast::ExpressionList params;
               if (intrinsic->Type() == sem::IntrinsicType::kTextureLoad) {
-                auto* coordsParam = ctx.Clone(call_expr->args()[1]);
+                auto* coordsParam = ctx.Clone(call_expr->args[1]);
                 auto* levelParam = ctx.dst->Expr(0);
                 params = {externalTextureParam, coordsParam, levelParam};
               } else if (intrinsic->Type() ==
                          sem::IntrinsicType::kTextureSampleLevel) {
-                auto* samplerParam = ctx.Clone(call_expr->args()[1]);
-                auto* coordsParam = ctx.Clone(call_expr->args()[2]);
+                auto* samplerParam = ctx.Clone(call_expr->args[1]);
+                auto* coordsParam = ctx.Clone(call_expr->args[2]);
                 auto* levelParam = ctx.dst->Expr(0.0f);
                 params = {externalTextureParam, samplerParam, coordsParam,
                           levelParam};
@@ -107,18 +107,18 @@
   // Scan the AST nodes for external texture declarations.
   for (auto* node : ctx.src->ASTNodes().Objects()) {
     if (auto* var = node->As<ast::Variable>()) {
-      if (::tint::Is<ast::ExternalTexture>(var->type())) {
+      if (::tint::Is<ast::ExternalTexture>(var->type)) {
         // Replace a single-plane external texture with a 2D, f32 sampled
         // texture.
         auto* newType = ctx.dst->ty.sampled_texture(ast::TextureDimension::k2d,
                                                     ctx.dst->ty.f32());
-        auto clonedSrc = ctx.Clone(var->source());
-        auto clonedSym = ctx.Clone(var->symbol());
-        auto* clonedConstructor = ctx.Clone(var->constructor());
-        auto clonedDecorations = ctx.Clone(var->decorations());
+        auto clonedSrc = ctx.Clone(var->source);
+        auto clonedSym = ctx.Clone(var->symbol);
+        auto* clonedConstructor = ctx.Clone(var->constructor);
+        auto clonedDecorations = ctx.Clone(var->decorations);
         auto* newVar = ctx.dst->create<ast::Variable>(
-            clonedSrc, clonedSym, var->declared_storage_class(),
-            var->declared_access(), newType, var->is_const(), clonedConstructor,
+            clonedSrc, clonedSym, var->declared_storage_class,
+            var->declared_access, newType, var->is_const, clonedConstructor,
             clonedDecorations);
 
         ctx.Replace(var, newVar);
diff --git a/src/transform/first_index_offset.cc b/src/transform/first_index_offset.cc
index 8a28364..0ae7ffa 100644
--- a/src/transform/first_index_offset.cc
+++ b/src/transform/first_index_offset.cc
@@ -80,9 +80,9 @@
   // parameters) or structure member accesses.
   for (auto* node : ctx.src->ASTNodes().Objects()) {
     if (auto* var = node->As<ast::Variable>()) {
-      for (ast::Decoration* dec : var->decorations()) {
+      for (ast::Decoration* dec : var->decorations) {
         if (auto* builtin_dec = dec->As<ast::BuiltinDecoration>()) {
-          ast::Builtin builtin = builtin_dec->value();
+          ast::Builtin builtin = builtin_dec->builtin;
           if (builtin == ast::Builtin::kVertexIndex) {
             auto* sem_var = ctx.src->Sem().Get(var);
             builtin_vars.emplace(sem_var, kFirstVertexName);
@@ -97,9 +97,9 @@
       }
     }
     if (auto* member = node->As<ast::StructMember>()) {
-      for (ast::Decoration* dec : member->decorations()) {
+      for (ast::Decoration* dec : member->decorations) {
         if (auto* builtin_dec = dec->As<ast::BuiltinDecoration>()) {
-          ast::Builtin builtin = builtin_dec->value();
+          ast::Builtin builtin = builtin_dec->builtin;
           if (builtin == ast::Builtin::kVertexIndex) {
             auto* sem_mem = ctx.src->Sem().Get(member);
             builtin_members.emplace(sem_mem, kFirstVertexName);
diff --git a/src/transform/fold_constants.cc b/src/transform/fold_constants.cc
index 4868b3c..54f7f15 100644
--- a/src/transform/fold_constants.cc
+++ b/src/transform/fold_constants.cc
@@ -51,7 +51,7 @@
 
     // If original ctor expression had no init values, don't replace the
     // expression
-    if (ctor->values().size() == 0) {
+    if (ctor->values.size() == 0) {
       return nullptr;
     }
 
@@ -68,7 +68,7 @@
       // create it with 3. So what we do is construct with vec_size args,
       // except if the original vector was single-value initialized, in
       // which case, we only construct with one arg again.
-      uint32_t ctor_size = (ctor->values().size() == 1) ? 1 : vec_size;
+      uint32_t ctor_size = (ctor->values.size() == 1) ? 1 : vec_size;
 
       ast::ExpressionList ctors;
       for (uint32_t i = 0; i < ctor_size; ++i) {
diff --git a/src/transform/fold_trivial_single_use_lets.cc b/src/transform/fold_trivial_single_use_lets.cc
index d1deb8f..78d77e3 100644
--- a/src/transform/fold_trivial_single_use_lets.cc
+++ b/src/transform/fold_trivial_single_use_lets.cc
@@ -32,11 +32,11 @@
   if (!var_decl) {
     return nullptr;
   }
-  auto* var = var_decl->variable();
-  if (!var->is_const()) {
+  auto* var = var_decl->variable;
+  if (!var->is_const) {
     return nullptr;
   }
-  auto* ctor = var->constructor();
+  auto* ctor = var->constructor;
   if (!IsAnyOf<ast::IdentifierExpression, ast::ScalarConstructorExpression>(
           ctor)) {
     return nullptr;
@@ -55,11 +55,11 @@
                                    DataMap&) {
   for (auto* node : ctx.src->ASTNodes().Objects()) {
     if (auto* block = node->As<ast::BlockStatement>()) {
-      auto& stmts = block->statements();
+      auto& stmts = block->statements;
       for (size_t stmt_idx = 0; stmt_idx < stmts.size(); stmt_idx++) {
         auto* stmt = stmts[stmt_idx];
         if (auto* let_decl = AsTrivialLetDecl(stmt)) {
-          auto* let = let_decl->variable();
+          auto* let = let_decl->variable;
           auto* sem_let = ctx.src->Sem().Get(let);
           auto& users = sem_let->Users();
           if (users.size() != 1) {
@@ -73,7 +73,7 @@
             if (user_stmt == stmts[i]) {
               auto* user_expr = user->Declaration();
               ctx.Remove(stmts, let_decl);
-              ctx.Replace(user_expr, ctx.Clone(let->constructor()));
+              ctx.Replace(user_expr, ctx.Clone(let->constructor));
             }
             if (!AsTrivialLetDecl(stmts[i])) {
               // Stop if we hit a statement that isn't the single use of the
diff --git a/src/transform/for_loop_to_loop.cc b/src/transform/for_loop_to_loop.cc
index 5f553a8..6b43064 100644
--- a/src/transform/for_loop_to_loop.cc
+++ b/src/transform/for_loop_to_loop.cc
@@ -28,7 +28,7 @@
 void ForLoopToLoop::Run(CloneContext& ctx, const DataMap&, DataMap&) {
   ctx.ReplaceAll([&](ast::ForLoopStatement* for_loop) -> ast::Statement* {
     ast::StatementList stmts;
-    if (auto* cond = for_loop->condition()) {
+    if (auto* cond = for_loop->condition) {
       // !condition
       auto* not_cond = ctx.dst->create<ast::UnaryOpExpression>(
           ast::UnaryOp::kNot, ctx.Clone(cond));
@@ -39,19 +39,19 @@
       // if (!condition) { break; }
       stmts.emplace_back(ctx.dst->If(not_cond, break_body));
     }
-    for (auto* stmt : for_loop->body()->statements()) {
+    for (auto* stmt : for_loop->body->statements) {
       stmts.emplace_back(ctx.Clone(stmt));
     }
 
     ast::BlockStatement* continuing = nullptr;
-    if (auto* cont = for_loop->continuing()) {
+    if (auto* cont = for_loop->continuing) {
       continuing = ctx.dst->Block(ctx.Clone(cont));
     }
 
     auto* body = ctx.dst->Block(stmts);
     auto* loop = ctx.dst->create<ast::LoopStatement>(body, continuing);
 
-    if (auto* init = for_loop->initializer()) {
+    if (auto* init = for_loop->initializer) {
       return ctx.dst->Block(ctx.Clone(init), loop);
     }
 
diff --git a/src/transform/inline_pointer_lets.cc b/src/transform/inline_pointer_lets.cc
index 38d905c..85287a2 100644
--- a/src/transform/inline_pointer_lets.cc
+++ b/src/transform/inline_pointer_lets.cc
@@ -44,21 +44,21 @@
                               ast::Expression* expr,
                               F&& cb) {
   if (auto* a = expr->As<ast::ArrayAccessorExpression>()) {
-    CollectSavedArrayIndices(program, a->array(), cb);
+    CollectSavedArrayIndices(program, a->array, cb);
 
-    if (!a->idx_expr()->Is<ast::ScalarConstructorExpression>()) {
-      cb(a->idx_expr());
+    if (!a->index->Is<ast::ScalarConstructorExpression>()) {
+      cb(a->index);
     }
     return;
   }
 
   if (auto* m = expr->As<ast::MemberAccessorExpression>()) {
-    CollectSavedArrayIndices(program, m->structure(), cb);
+    CollectSavedArrayIndices(program, m->structure, cb);
     return;
   }
 
   if (auto* u = expr->As<ast::UnaryOpExpression>()) {
-    CollectSavedArrayIndices(program, u->expr(), cb);
+    CollectSavedArrayIndices(program, u->expr, cb);
     return;
   }
 
@@ -119,7 +119,7 @@
           // TINT_SCOPED_ASSIGNMENT provides a stack of PtrLet*, this is
           // required to handle the 'chaining' of inlined `let`s.
           TINT_SCOPED_ASSIGNMENT(current_ptr_let, ptr_let);
-          return ctx.Clone(var->constructor());
+          return ctx.Clone(var->constructor);
         }
       }
     }
@@ -131,11 +131,11 @@
   // permitted.
   for (auto* node : ctx.src->ASTNodes().Objects()) {
     if (auto* let = node->As<ast::VariableDeclStatement>()) {
-      if (!let->variable()->is_const()) {
+      if (!let->variable->is_const) {
         continue;  // Not a `let` declaration. Ignore.
       }
 
-      auto* var = ctx.src->Sem().Get(let->variable());
+      auto* var = ctx.src->Sem().Get(let->variable);
       if (!var->Type()->Is<sem::Pointer>()) {
         continue;  // Not a pointer type. Ignore.
       }
@@ -149,12 +149,12 @@
       // Scan the initializer expression for array index expressions that need
       // to be hoist to temporary "saved" variables.
       CollectSavedArrayIndices(
-          ctx.src, var->Declaration()->constructor(),
+          ctx.src, var->Declaration()->constructor,
           [&](ast::Expression* idx_expr) {
             // We have a sub-expression that needs to be saved.
             // Create a new variable
             auto saved_name = ctx.dst->Symbols().New(
-                ctx.src->Symbols().NameFor(var->Declaration()->symbol()) +
+                ctx.src->Symbols().NameFor(var->Declaration()->symbol) +
                 "_save");
             auto* saved = ctx.dst->Decl(
                 ctx.dst->Const(saved_name, nullptr, ctx.Clone(idx_expr)));
@@ -165,7 +165,7 @@
             // Note that repeated calls to InsertAfter() with the same `after`
             // argument will result in nodes to inserted in the order the calls
             // are made (last call is inserted last).
-            ctx.InsertAfter(block->statements(), let, saved);
+            ctx.InsertAfter(block->statements, let, saved);
             // Record the substitution of `idx_expr` to the saved variable with
             // the symbol `saved_name`. This will be used by the ReplaceAll()
             // handler above.
@@ -174,7 +174,7 @@
 
       // Record the pointer-typed `let` declaration.
       // This will be used by the ReplaceAll() handler above.
-      ptr_lets.emplace(let->variable(), std::move(ptr_let));
+      ptr_lets.emplace(let->variable, std::move(ptr_let));
       // As the original `let` declaration will be fully inlined, there's no
       // need for the original declaration to exist. Remove it.
       RemoveStatement(ctx, let);
diff --git a/src/transform/loop_to_for_loop.cc b/src/transform/loop_to_for_loop.cc
index 85f7a84..34d4524 100644
--- a/src/transform/loop_to_for_loop.cc
+++ b/src/transform/loop_to_for_loop.cc
@@ -30,10 +30,10 @@
 namespace {
 
 bool IsBlockWithSingleBreak(ast::BlockStatement* block) {
-  if (block->size() != 1) {
+  if (block->statements.size() != 1) {
     return false;
   }
-  return block->statements()[0]->Is<ast::BreakStatement>();
+  return block->statements[0]->Is<ast::BreakStatement>();
 }
 
 bool IsVarUsedByStmt(const sem::Info& sem,
@@ -67,7 +67,7 @@
     // Examples:
     //   loop {  if (condition) { break; } ... }
     //   loop {  if (condition) {} else { break; } ... }
-    auto& stmts = loop->body()->statements();
+    auto& stmts = loop->body->statements;
     if (stmts.empty()) {
       return nullptr;
     }
@@ -77,13 +77,12 @@
     }
 
     bool negate_condition = false;
-    if (IsBlockWithSingleBreak(if_stmt->body()) &&
-        if_stmt->else_statements().empty()) {
+    if (IsBlockWithSingleBreak(if_stmt->body) &&
+        if_stmt->else_statements.empty()) {
       negate_condition = true;
-    } else if (if_stmt->body()->empty() &&
-               if_stmt->else_statements().size() == 1 &&
-               if_stmt->else_statements()[0]->condition() == nullptr &&
-               IsBlockWithSingleBreak(if_stmt->else_statements()[0]->body())) {
+    } else if (if_stmt->body->Empty() && if_stmt->else_statements.size() == 1 &&
+               if_stmt->else_statements[0]->condition == nullptr &&
+               IsBlockWithSingleBreak(if_stmt->else_statements[0]->body)) {
       negate_condition = false;
     } else {
       return nullptr;
@@ -92,12 +91,12 @@
     // The continuing block must be empty or contain a single, assignment or
     // function call statement.
     ast::Statement* continuing = nullptr;
-    if (auto* loop_cont = loop->continuing()) {
-      if (loop_cont->statements().size() != 1) {
+    if (auto* loop_cont = loop->continuing) {
+      if (loop_cont->statements.size() != 1) {
         return nullptr;
       }
 
-      continuing = loop_cont->statements()[0];
+      continuing = loop_cont->statements[0];
       if (!continuing
                ->IsAnyOf<ast::AssignmentStatement, ast::CallStatement>()) {
         return nullptr;
@@ -105,10 +104,9 @@
 
       // And the continuing statement must not use any of the variables declared
       // in the loop body.
-      for (auto* stmt : loop->body()->statements()) {
+      for (auto* stmt : loop->body->statements) {
         if (auto* var_decl = stmt->As<ast::VariableDeclStatement>()) {
-          if (IsVarUsedByStmt(ctx.src->Sem(), var_decl->variable(),
-                              continuing)) {
+          if (IsVarUsedByStmt(ctx.src->Sem(), var_decl->variable, continuing)) {
             return nullptr;
           }
         }
@@ -117,7 +115,7 @@
       continuing = ctx.Clone(continuing);
     }
 
-    auto* condition = ctx.Clone(if_stmt->condition());
+    auto* condition = ctx.Clone(if_stmt->condition);
     if (negate_condition) {
       condition = ctx.dst->create<ast::UnaryOpExpression>(ast::UnaryOp::kNot,
                                                           condition);
@@ -125,8 +123,8 @@
 
     ast::Statement* initializer = nullptr;
 
-    ctx.Remove(loop->body()->statements(), if_stmt);
-    auto* body = ctx.Clone(loop->body());
+    ctx.Remove(loop->body->statements, if_stmt);
+    auto* body = ctx.Clone(loop->body);
     return ctx.dst->create<ast::ForLoopStatement>(initializer, condition,
                                                   continuing, body);
   });
diff --git a/src/transform/module_scope_var_to_entry_point_param.cc b/src/transform/module_scope_var_to_entry_point_param.cc
index f0a3ee7f..f71a010 100644
--- a/src/transform/module_scope_var_to_entry_point_param.cc
+++ b/src/transform/module_scope_var_to_entry_point_param.cc
@@ -127,10 +127,10 @@
         ident_to_address_of;
     for (auto* node : ctx.src->ASTNodes().Objects()) {
       auto* address_of = node->As<ast::UnaryOpExpression>();
-      if (!address_of || address_of->op() != ast::UnaryOp::kAddressOf) {
+      if (!address_of || address_of->op != ast::UnaryOp::kAddressOf) {
         continue;
       }
-      if (auto* ident = address_of->expr()->As<ast::IdentifierExpression>()) {
+      if (auto* ident = address_of->expr->As<ast::IdentifierExpression>()) {
         ident_to_address_of[ident] = address_of;
       }
     }
@@ -180,10 +180,10 @@
                 ctx.dst->ASTNodes().Create<ast::DisableValidationDecoration>(
                     ctx.dst->ID(),
                     ast::DisabledValidation::kEntryPointParameter);
-            auto decos = ctx.Clone(var->Declaration()->decorations());
+            auto decos = ctx.Clone(var->Declaration()->decorations);
             decos.push_back(disable_validation);
             auto* param = ctx.dst->Param(new_var_symbol, store_type(), decos);
-            ctx.InsertFront(func_ast->params(), param);
+            ctx.InsertFront(func_ast->params, param);
           } else if (var->StorageClass() == ast::StorageClass::kWorkgroup &&
                      ContainsMatrix(var->Type())) {
             // Due to a bug in the MSL compiler, we use a threadgroup memory
@@ -192,7 +192,7 @@
             // TODO(jrprice): Do this for all other workgroup variables too.
 
             // Create a member in the workgroup parameter struct.
-            auto member = ctx.Clone(var->Declaration()->symbol());
+            auto member = ctx.Clone(var->Declaration()->symbol);
             workgroup_parameter_members.push_back(
                 ctx.dst->Member(member, store_type()));
             CloneStructTypes(var->Type()->UnwrapRef());
@@ -205,7 +205,7 @@
                                ctx.dst->ty.pointer(
                                    store_type(), ast::StorageClass::kWorkgroup),
                                member_ptr);
-            ctx.InsertFront(func_ast->body()->statements(),
+            ctx.InsertFront(func_ast->body->statements,
                             ctx.dst->Decl(local_var));
             is_pointer = true;
           } else {
@@ -216,11 +216,11 @@
                 ctx.dst->ASTNodes().Create<ast::DisableValidationDecoration>(
                     ctx.dst->ID(),
                     ast::DisabledValidation::kIgnoreStorageClass);
-            auto* constructor = ctx.Clone(var->Declaration()->constructor());
+            auto* constructor = ctx.Clone(var->Declaration()->constructor);
             auto* local_var = ctx.dst->Var(
                 new_var_symbol, store_type(), var->StorageClass(), constructor,
                 ast::DecorationList{disable_validation});
-            ctx.InsertFront(func_ast->body()->statements(),
+            ctx.InsertFront(func_ast->body->statements,
                             ctx.dst->Decl(local_var));
           }
         } else {
@@ -240,7 +240,7 @@
                     ast::DisabledValidation::kIgnoreInvalidPointerArgument));
           }
           ctx.InsertBack(
-              func_ast->params(),
+              func_ast->params,
               ctx.dst->Param(new_var_symbol, param_type, attributes));
         }
 
@@ -282,12 +282,12 @@
                 ctx.dst->ID(), ast::DisabledValidation::kEntryPointParameter);
         auto* param =
             ctx.dst->Param(workgroup_param(), param_type, {disable_validation});
-        ctx.InsertFront(func_ast->params(), param);
+        ctx.InsertFront(func_ast->params, param);
       }
 
       // Pass the variables as pointers to any functions that need them.
       for (auto* call : calls_to_replace[func_ast]) {
-        auto* target = ctx.src->AST().Functions().Find(call->func()->symbol());
+        auto* target = ctx.src->AST().Functions().Find(call->func->symbol);
         auto* target_sem = ctx.src->Sem().Get(target);
 
         // Add new arguments for any variables that are needed by the callee.
@@ -305,7 +305,7 @@
             if (is_entry_point && !is_handle && !is_workgroup_matrix) {
               arg = ctx.dst->AddressOf(arg);
             }
-            ctx.InsertBack(call->args(), arg);
+            ctx.InsertBack(call->args, arg);
           }
         }
       }
diff --git a/src/transform/num_workgroups_from_uniform.cc b/src/transform/num_workgroups_from_uniform.cc
index ae0148e..4b2815c 100644
--- a/src/transform/num_workgroups_from_uniform.cc
+++ b/src/transform/num_workgroups_from_uniform.cc
@@ -73,7 +73,7 @@
   std::unordered_set<Accessor, Accessor::Hasher> to_replace;
   for (auto* func : ctx.src->AST().Functions()) {
     // num_workgroups is only valid for compute stages.
-    if (func->pipeline_stage() != ast::PipelineStage::kCompute) {
+    if (func->PipelineStage() != ast::PipelineStage::kCompute) {
       continue;
     }
 
@@ -87,8 +87,8 @@
 
       for (auto* member : str->Members()) {
         auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(
-            member->Declaration()->decorations());
-        if (!builtin || builtin->value() != ast::Builtin::kNumWorkgroups) {
+            member->Declaration()->decorations);
+        if (!builtin || builtin->builtin != ast::Builtin::kNumWorkgroups) {
           continue;
         }
 
@@ -96,18 +96,18 @@
         // we will replace later. We currently have no way to get from the
         // parameter directly to the member accessor expressions that use it.
         to_replace.insert(
-            {param->Declaration()->symbol(), member->Declaration()->symbol()});
+            {param->Declaration()->symbol, member->Declaration()->symbol});
 
         // Remove the struct member.
         // The CanonicalizeEntryPointIO transform will have generated this
         // struct uniquely for this particular entry point, so we know that
         // there will be no other uses of this struct in the module and that we
         // can safely modify it here.
-        ctx.Remove(str->Declaration()->members(), member->Declaration());
+        ctx.Remove(str->Declaration()->members, member->Declaration());
 
         // If this is the only member, remove the struct and parameter too.
         if (str->Members().size() == 1) {
-          ctx.Remove(func->params(), param->Declaration());
+          ctx.Remove(func->params, param->Declaration());
           ctx.Remove(ctx.src->AST().GlobalDeclarations(), str->Declaration());
         }
       }
@@ -140,13 +140,13 @@
     if (!accessor) {
       continue;
     }
-    auto* ident = accessor->structure()->As<ast::IdentifierExpression>();
+    auto* ident = accessor->structure->As<ast::IdentifierExpression>();
     if (!ident) {
       continue;
     }
 
-    if (to_replace.count({ident->symbol(), accessor->member()->symbol()})) {
-      ctx.Replace(accessor, ctx.dst->MemberAccessor(get_ubo()->symbol(),
+    if (to_replace.count({ident->symbol, accessor->member->symbol})) {
+      ctx.Replace(accessor, ctx.dst->MemberAccessor(get_ubo()->symbol,
                                                     kNumWorkgroupsMemberName));
     }
   }
diff --git a/src/transform/pad_array_elements.cc b/src/transform/pad_array_elements.cc
index 04358bd..ff3f8df 100644
--- a/src/transform/pad_array_elements.cc
+++ b/src/transform/pad_array_elements.cc
@@ -118,7 +118,7 @@
   ctx.ReplaceAll(
       [&](ast::ArrayAccessorExpression* accessor) -> ast::Expression* {
         if (auto* array = tint::As<sem::Array>(
-                sem.Get(accessor->array())->Type()->UnwrapRef())) {
+                sem.Get(accessor->array)->Type()->UnwrapRef())) {
           if (pad(array)) {
             // Array element is wrapped in a structure. Emit a member accessor
             // to get to the actual array element.
@@ -136,11 +136,11 @@
             tint::As<sem::Array>(sem.Get(ctor)->Type()->UnwrapRef())) {
       if (auto p = pad(array)) {
         auto* arr_ty = p();
-        auto el_typename = arr_ty->type()->As<ast::TypeName>()->name();
+        auto el_typename = arr_ty->type->As<ast::TypeName>()->name;
 
         ast::ExpressionList args;
-        args.reserve(ctor->values().size());
-        for (auto* arg : ctor->values()) {
+        args.reserve(ctor->values.size());
+        for (auto* arg : ctor->values) {
           args.emplace_back(ctx.dst->Construct(
               ctx.dst->create<ast::TypeName>(el_typename), ctx.Clone(arg)));
         }
diff --git a/src/transform/promote_initializers_to_const_var.cc b/src/transform/promote_initializers_to_const_var.cc
index 87e7976..4128d6f 100644
--- a/src/transform/promote_initializers_to_const_var.cc
+++ b/src/transform/promote_initializers_to_const_var.cc
@@ -68,7 +68,7 @@
       auto* src_stmt = src_sem_stmt->Declaration();
 
       if (auto* src_var_decl = src_stmt->As<ast::VariableDeclStatement>()) {
-        if (src_var_decl->variable()->constructor() == src_init) {
+        if (src_var_decl->variable->constructor == src_init) {
           // This statement is just a variable declaration with the initializer
           // as the constructor value. This is what we're attempting to
           // transform to, and so ignore.
@@ -81,7 +81,7 @@
         // Create a new symbol for the constant
         auto dst_symbol = ctx.dst->Sym();
         // Clone the type
-        auto* dst_ty = ctx.Clone(src_init->type());
+        auto* dst_ty = ctx.Clone(src_init->type);
         // Clone the initializer
         auto* dst_init = ctx.Clone(src_init);
         // Construct the constant that holds the hoisted initializer
@@ -92,7 +92,7 @@
         auto* dst_ident = ctx.dst->Expr(dst_symbol);
 
         // Insert the constant before the usage
-        ctx.InsertBefore(src_sem_stmt->Block()->Declaration()->statements(),
+        ctx.InsertBefore(src_sem_stmt->Block()->Declaration()->statements,
                          src_stmt, dst_var_decl);
         // Replace the inlined initializer with a reference to the constant
         ctx.Replace(src_init, dst_ident);
diff --git a/src/transform/renamer.cc b/src/transform/renamer.cc
index 9a89cf8..e9e2f6a 100644
--- a/src/transform/renamer.cc
+++ b/src/transform/renamer.cc
@@ -1115,11 +1115,11 @@
         continue;
       }
       if (sem->Is<sem::Swizzle>()) {
-        preserve.emplace(member->member());
-      } else if (auto* str_expr = in->Sem().Get(member->structure())) {
+        preserve.emplace(member->member);
+      } else if (auto* str_expr = in->Sem().Get(member->structure)) {
         if (auto* ty = str_expr->Type()->UnwrapRef()->As<sem::Struct>()) {
           if (ty->Declaration() == nullptr) {  // Builtin structure
-            preserve.emplace(member->member());
+            preserve.emplace(member->member);
           }
         }
       }
@@ -1131,7 +1131,7 @@
         continue;
       }
       if (sem->Target()->Is<sem::Intrinsic>()) {
-        preserve.emplace(call->func());
+        preserve.emplace(call->func);
       }
     }
   }
@@ -1190,11 +1190,11 @@
   ctx.ReplaceAll(
       [&](ast::IdentifierExpression* ident) -> ast::IdentifierExpression* {
         if (preserve.count(ident)) {
-          auto sym_in = ident->symbol();
+          auto sym_in = ident->symbol;
           auto str = in->Symbols().NameFor(sym_in);
           auto sym_out = out.Symbols().Register(str);
           return ctx.dst->create<ast::IdentifierExpression>(
-              ctx.Clone(ident->source()), sym_out);
+              ctx.Clone(ident->source), sym_out);
         }
         return nullptr;  // Clone ident. Uses the symbol remapping above.
       });
diff --git a/src/transform/robustness.cc b/src/transform/robustness.cc
index a5f1eac..9aa5a3e 100644
--- a/src/transform/robustness.cc
+++ b/src/transform/robustness.cc
@@ -46,7 +46,7 @@
   /// @return the clamped replacement expression, or nullptr if `expr` should be
   /// cloned without changes.
   ast::ArrayAccessorExpression* Transform(ast::ArrayAccessorExpression* expr) {
-    auto* ret_type = ctx.src->Sem().Get(expr->array())->Type()->UnwrapRef();
+    auto* ret_type = ctx.src->Sem().Get(expr->array)->Type()->UnwrapRef();
 
     ProgramBuilder& b = *ctx.dst;
     using u32 = ProgramBuilder::u32;
@@ -78,11 +78,11 @@
     if (size.u32 == 0) {
       if (!ret_type->Is<sem::Array>()) {
         b.Diagnostics().add_error(diag::System::Transform,
-                                  "invalid 0 sized non-array", expr->source());
+                                  "invalid 0 sized non-array", expr->source);
         return nullptr;
       }
       // Runtime sized array
-      auto* arr = ctx.Clone(expr->array());
+      auto* arr = ctx.Clone(expr->array);
       size.expr = b.Call("arrayLength", b.AddressOf(arr));
     }
 
@@ -101,7 +101,7 @@
 
     Value idx;  // index value
 
-    auto* idx_sem = ctx.src->Sem().Get(expr->idx_expr());
+    auto* idx_sem = ctx.src->Sem().Get(expr->index);
     auto* idx_ty = idx_sem->Type()->UnwrapRef();
     if (!idx_ty->IsAnyOf<sem::I32, sem::U32>()) {
       TINT_ICE(Transform, b.Diagnostics())
@@ -121,12 +121,12 @@
         b.Diagnostics().add_error(diag::System::Transform,
                                   "unsupported constant value for accessor: " +
                                       idx_constant.Type()->type_name(),
-                                  expr->source());
+                                  expr->source);
         return nullptr;
       }
     } else {
       // Dynamic value index
-      idx.expr = ctx.Clone(expr->idx_expr());
+      idx.expr = ctx.Clone(expr->index);
       idx.is_signed = idx_ty->Is<sem::I32>();
     }
 
@@ -178,8 +178,8 @@
     }
 
     // Clone arguments outside of create() call to have deterministic ordering
-    auto src = ctx.Clone(expr->source());
-    auto* arr = ctx.Clone(expr->array());
+    auto src = ctx.Clone(expr->source);
+    auto* arr = ctx.Clone(expr->array);
     return b.IndexAccessor(src, arr, idx.expr);
   }
 
@@ -214,8 +214,8 @@
     auto array_idx = signature.IndexOf(sem::ParameterUsage::kArrayIndex);
     auto level_idx = signature.IndexOf(sem::ParameterUsage::kLevel);
 
-    auto* texture_arg = expr->args()[texture_idx];
-    auto* coords_arg = expr->args()[coords_idx];
+    auto* texture_arg = expr->args[texture_idx];
+    auto* coords_arg = expr->args[coords_idx];
     auto* coords_ty = intrinsic->Parameters()[coords_idx]->Type();
 
     // If the level is provided, then we need to clamp this. As the level is
@@ -226,7 +226,7 @@
     std::function<ast::Expression*()> level_arg;
     if (level_idx >= 0) {
       level_arg = [&] {
-        auto* arg = expr->args()[level_idx];
+        auto* arg = expr->args[level_idx];
         auto* num_levels = b.Call("textureNumLevels", ctx.Clone(texture_arg));
         auto* zero = b.Expr(0);
         auto* max = ctx.dst->Sub(num_levels, 1);
@@ -250,7 +250,7 @@
 
     // Clamp the array_index argument, if provided
     if (array_idx >= 0) {
-      auto* arg = expr->args()[array_idx];
+      auto* arg = expr->args[array_idx];
       auto* num_layers = b.Call("textureNumLayers", ctx.Clone(texture_arg));
       auto* zero = b.Expr(0);
       auto* max = ctx.dst->Sub(num_layers, 1);
@@ -260,7 +260,7 @@
 
     // Clamp the level argument, if provided
     if (level_idx >= 0) {
-      auto* arg = expr->args()[level_idx];
+      auto* arg = expr->args[level_idx];
       ctx.Replace(arg, level_arg ? level_arg() : ctx.dst->Expr(0));
     }
 
diff --git a/src/transform/simplify.cc b/src/transform/simplify.cc
index c007d35..2d414d7 100644
--- a/src/transform/simplify.cc
+++ b/src/transform/simplify.cc
@@ -37,16 +37,16 @@
 void Simplify::Run(CloneContext& ctx, const DataMap&, DataMap&) {
   ctx.ReplaceAll([&](ast::Expression* expr) -> ast::Expression* {
     if (auto* outer = expr->As<ast::UnaryOpExpression>()) {
-      if (auto* inner = outer->expr()->As<ast::UnaryOpExpression>()) {
-        if (outer->op() == ast::UnaryOp::kAddressOf &&
-            inner->op() == ast::UnaryOp::kIndirection) {
+      if (auto* inner = outer->expr->As<ast::UnaryOpExpression>()) {
+        if (outer->op == ast::UnaryOp::kAddressOf &&
+            inner->op == ast::UnaryOp::kIndirection) {
           // &(*(expr)) => expr
-          return ctx.Clone(inner->expr());
+          return ctx.Clone(inner->expr);
         }
-        if (outer->op() == ast::UnaryOp::kIndirection &&
-            inner->op() == ast::UnaryOp::kAddressOf) {
+        if (outer->op == ast::UnaryOp::kIndirection &&
+            inner->op == ast::UnaryOp::kAddressOf) {
           // *(&(expr)) => expr
-          return ctx.Clone(inner->expr());
+          return ctx.Clone(inner->expr);
         }
       }
     }
diff --git a/src/transform/single_entry_point.cc b/src/transform/single_entry_point.cc
index 264d5fa..9a3135a 100644
--- a/src/transform/single_entry_point.cc
+++ b/src/transform/single_entry_point.cc
@@ -47,7 +47,7 @@
     if (!f->IsEntryPoint()) {
       continue;
     }
-    if (ctx.src->Symbols().NameFor(f->symbol()) == cfg->entry_point_name) {
+    if (ctx.src->Symbols().NameFor(f->symbol) == cfg->entry_point_name) {
       entry_point = f;
       break;
     }
@@ -74,11 +74,11 @@
       // TODO(jrprice): Strip unused types.
       ctx.dst->AST().AddTypeDecl(ctx.Clone(ty));
     } else if (auto* var = decl->As<ast::Variable>()) {
-      if (var->is_const() || referenced_vars.count(var)) {
+      if (var->is_const || referenced_vars.count(var)) {
         ctx.dst->AST().AddGlobalVariable(ctx.Clone(var));
       }
     } else if (auto* func = decl->As<ast::Function>()) {
-      if (sem.Get(func)->HasAncestorEntryPoint(entry_point->symbol())) {
+      if (sem.Get(func)->HasAncestorEntryPoint(entry_point->symbol)) {
         ctx.dst->AST().AddFunction(ctx.Clone(func));
       }
     } else {
diff --git a/src/transform/transform.cc b/src/transform/transform.cc
index 8b199a5..32ca39d 100644
--- a/src/transform/transform.cc
+++ b/src/transform/transform.cc
@@ -78,7 +78,7 @@
 void Transform::RemoveStatement(CloneContext& ctx, ast::Statement* stmt) {
   auto* sem = ctx.src->Sem().Get(stmt);
   if (auto* block = tint::As<sem::BlockStatement>(sem->Parent())) {
-    ctx.Remove(block->Declaration()->statements(), stmt);
+    ctx.Remove(block->Declaration()->statements, stmt);
     return;
   }
   if (tint::Is<sem::ForLoopStatement>(sem->Parent())) {
@@ -127,7 +127,7 @@
     }
   }
   if (auto* s = ty->As<sem::Struct>()) {
-    return ctx.dst->create<ast::TypeName>(ctx.Clone(s->Declaration()->name()));
+    return ctx.dst->create<ast::TypeName>(ctx.Clone(s->Declaration()->name));
   }
   if (auto* s = ty->As<sem::Reference>()) {
     return CreateASTTypeFor(ctx, s->StoreType());
diff --git a/src/transform/transform_test.cc b/src/transform/transform_test.cc
index 7cd0cdc..6b9d352 100644
--- a/src/transform/transform_test.cc
+++ b/src/transform/transform_test.cc
@@ -62,9 +62,9 @@
     return b.create<sem::Matrix>(column_type, 3u);
   });
   ASSERT_TRUE(mat->Is<ast::Matrix>());
-  ASSERT_TRUE(mat->As<ast::Matrix>()->type()->Is<ast::F32>());
-  ASSERT_EQ(mat->As<ast::Matrix>()->columns(), 3u);
-  ASSERT_EQ(mat->As<ast::Matrix>()->rows(), 2u);
+  ASSERT_TRUE(mat->As<ast::Matrix>()->type->Is<ast::F32>());
+  ASSERT_EQ(mat->As<ast::Matrix>()->columns, 3u);
+  ASSERT_EQ(mat->As<ast::Matrix>()->rows, 2u);
 }
 
 TEST_F(CreateASTTypeForTest, Vector) {
@@ -72,8 +72,8 @@
     return b.create<sem::Vector>(b.create<sem::F32>(), 2);
   });
   ASSERT_TRUE(vec->Is<ast::Vector>());
-  ASSERT_TRUE(vec->As<ast::Vector>()->type()->Is<ast::F32>());
-  ASSERT_EQ(vec->As<ast::Vector>()->size(), 2u);
+  ASSERT_TRUE(vec->As<ast::Vector>()->type->Is<ast::F32>());
+  ASSERT_EQ(vec->As<ast::Vector>()->width, 2u);
 }
 
 TEST_F(CreateASTTypeForTest, ArrayImplicitStride) {
@@ -81,15 +81,15 @@
     return b.create<sem::Array>(b.create<sem::F32>(), 2, 4, 4, 32u, 32u);
   });
   ASSERT_TRUE(arr->Is<ast::Array>());
-  ASSERT_TRUE(arr->As<ast::Array>()->type()->Is<ast::F32>());
-  ASSERT_EQ(arr->As<ast::Array>()->decorations().size(), 0u);
+  ASSERT_TRUE(arr->As<ast::Array>()->type->Is<ast::F32>());
+  ASSERT_EQ(arr->As<ast::Array>()->decorations.size(), 0u);
 
-  auto* size_expr =
-      arr->As<ast::Array>()->Size()->As<ast::ScalarConstructorExpression>();
-  ASSERT_NE(size_expr, nullptr);
-  auto* size = size_expr->literal()->As<ast::IntLiteral>();
+  auto* count_expr =
+      arr->As<ast::Array>()->count->As<ast::ScalarConstructorExpression>();
+  ASSERT_NE(count_expr, nullptr);
+  auto* size = count_expr->literal->As<ast::IntLiteral>();
   ASSERT_NE(size, nullptr);
-  EXPECT_EQ(size->value_as_i32(), 2);
+  EXPECT_EQ(size->ValueAsI32(), 2);
 }
 
 TEST_F(CreateASTTypeForTest, ArrayNonImplicitStride) {
@@ -97,35 +97,34 @@
     return b.create<sem::Array>(b.create<sem::F32>(), 2, 4, 4, 64u, 32u);
   });
   ASSERT_TRUE(arr->Is<ast::Array>());
-  ASSERT_TRUE(arr->As<ast::Array>()->type()->Is<ast::F32>());
-  ASSERT_EQ(arr->As<ast::Array>()->decorations().size(), 1u);
+  ASSERT_TRUE(arr->As<ast::Array>()->type->Is<ast::F32>());
+  ASSERT_EQ(arr->As<ast::Array>()->decorations.size(), 1u);
   ASSERT_TRUE(
-      arr->As<ast::Array>()->decorations()[0]->Is<ast::StrideDecoration>());
+      arr->As<ast::Array>()->decorations[0]->Is<ast::StrideDecoration>());
   ASSERT_EQ(arr->As<ast::Array>()
-                ->decorations()[0]
+                ->decorations[0]
                 ->As<ast::StrideDecoration>()
-                ->stride(),
+                ->stride,
             64u);
 
-  auto* size_expr =
-      arr->As<ast::Array>()->Size()->As<ast::ScalarConstructorExpression>();
-  ASSERT_NE(size_expr, nullptr);
-  auto* size = size_expr->literal()->As<ast::IntLiteral>();
+  auto* count_expr =
+      arr->As<ast::Array>()->count->As<ast::ScalarConstructorExpression>();
+  ASSERT_NE(count_expr, nullptr);
+  auto* size = count_expr->literal->As<ast::IntLiteral>();
   ASSERT_NE(size, nullptr);
-  EXPECT_EQ(size->value_as_i32(), 2);
+  EXPECT_EQ(size->ValueAsI32(), 2);
 }
 
 TEST_F(CreateASTTypeForTest, Struct) {
   auto* str = create([](ProgramBuilder& b) {
     auto* decl = b.Structure("S", {}, {});
-    return b.create<sem::Struct>(decl, decl->name(), sem::StructMemberList{},
+    return b.create<sem::Struct>(decl, decl->name, sem::StructMemberList{},
                                  4 /* align */, 4 /* size */,
                                  4 /* size_no_padding */);
   });
   ASSERT_TRUE(str->Is<ast::TypeName>());
-  EXPECT_EQ(
-      ast_type_builder.Symbols().NameFor(str->As<ast::TypeName>()->name()),
-      "S");
+  EXPECT_EQ(ast_type_builder.Symbols().NameFor(str->As<ast::TypeName>()->name),
+            "S");
 }
 
 }  // namespace
diff --git a/src/transform/vertex_pulling.cc b/src/transform/vertex_pulling.cc
index a44ba63..ae89e3d 100644
--- a/src/transform/vertex_pulling.cc
+++ b/src/transform/vertex_pulling.cc
@@ -726,27 +726,27 @@
   /// @param param the parameter to process
   void ProcessNonStructParameter(ast::Function* func, ast::Variable* param) {
     if (auto* location =
-            ast::GetDecoration<ast::LocationDecoration>(param->decorations())) {
+            ast::GetDecoration<ast::LocationDecoration>(param->decorations)) {
       // Create a function-scope variable to replace the parameter.
-      auto func_var_sym = ctx.Clone(param->symbol());
-      auto* func_var_type = ctx.Clone(param->type());
+      auto func_var_sym = ctx.Clone(param->symbol);
+      auto* func_var_type = ctx.Clone(param->type);
       auto* func_var = ctx.dst->Var(func_var_sym, func_var_type);
-      ctx.InsertFront(func->body()->statements(), ctx.dst->Decl(func_var));
+      ctx.InsertFront(func->body->statements, ctx.dst->Decl(func_var));
       // Capture mapping from location to the new variable.
       LocationInfo info;
       info.expr = [this, func_var]() { return ctx.dst->Expr(func_var); };
       info.type = ctx.src->Sem().Get(param)->Type();
-      location_info[location->value()] = info;
+      location_info[location->value] = info;
     } else if (auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(
-                   param->decorations())) {
+                   param->decorations)) {
       // Check for existing vertex_index and instance_index builtins.
-      if (builtin->value() == ast::Builtin::kVertexIndex) {
+      if (builtin->builtin == ast::Builtin::kVertexIndex) {
         vertex_index_expr = [this, param]() {
-          return ctx.dst->Expr(ctx.Clone(param->symbol()));
+          return ctx.dst->Expr(ctx.Clone(param->symbol));
         };
-      } else if (builtin->value() == ast::Builtin::kInstanceIndex) {
+      } else if (builtin->builtin == ast::Builtin::kInstanceIndex) {
         instance_index_expr = [this, param]() {
-          return ctx.dst->Expr(ctx.Clone(param->symbol()));
+          return ctx.dst->Expr(ctx.Clone(param->symbol));
         };
       }
       new_function_parameters.push_back(ctx.Clone(param));
@@ -767,32 +767,32 @@
   void ProcessStructParameter(ast::Function* func,
                               ast::Variable* param,
                               const ast::Struct* struct_ty) {
-    auto param_sym = ctx.Clone(param->symbol());
+    auto param_sym = ctx.Clone(param->symbol);
 
     // Process the struct members.
     bool has_locations = false;
     ast::StructMemberList members_to_clone;
-    for (auto* member : struct_ty->members()) {
-      auto member_sym = ctx.Clone(member->symbol());
+    for (auto* member : struct_ty->members) {
+      auto member_sym = ctx.Clone(member->symbol);
       std::function<ast::Expression*()> member_expr = [this, param_sym,
                                                        member_sym]() {
         return ctx.dst->MemberAccessor(param_sym, member_sym);
       };
 
       if (auto* location = ast::GetDecoration<ast::LocationDecoration>(
-              member->decorations())) {
+              member->decorations)) {
         // Capture mapping from location to struct member.
         LocationInfo info;
         info.expr = member_expr;
         info.type = ctx.src->Sem().Get(member)->Type();
-        location_info[location->value()] = info;
+        location_info[location->value] = info;
         has_locations = true;
       } else if (auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(
-                     member->decorations())) {
+                     member->decorations)) {
         // Check for existing vertex_index and instance_index builtins.
-        if (builtin->value() == ast::Builtin::kVertexIndex) {
+        if (builtin->builtin == ast::Builtin::kVertexIndex) {
           vertex_index_expr = member_expr;
-        } else if (builtin->value() == ast::Builtin::kInstanceIndex) {
+        } else if (builtin->builtin == ast::Builtin::kInstanceIndex) {
           instance_index_expr = member_expr;
         }
         members_to_clone.push_back(member);
@@ -809,16 +809,16 @@
     }
 
     // Create a function-scope variable to replace the parameter.
-    auto* func_var = ctx.dst->Var(param_sym, ctx.Clone(param->type()));
-    ctx.InsertFront(func->body()->statements(), ctx.dst->Decl(func_var));
+    auto* func_var = ctx.dst->Var(param_sym, ctx.Clone(param->type));
+    ctx.InsertFront(func->body->statements, ctx.dst->Decl(func_var));
 
     if (!members_to_clone.empty()) {
       // Create a new struct without the location attributes.
       ast::StructMemberList new_members;
       for (auto* member : members_to_clone) {
-        auto member_sym = ctx.Clone(member->symbol());
-        auto* member_type = ctx.Clone(member->type());
-        auto member_decos = ctx.Clone(member->decorations());
+        auto member_sym = ctx.Clone(member->symbol);
+        auto* member_type = ctx.Clone(member->type);
+        auto member_decos = ctx.Clone(member->decorations);
         new_members.push_back(
             ctx.dst->Member(member_sym, member_type, std::move(member_decos)));
       }
@@ -831,9 +831,9 @@
 
       // Copy values from the new parameter to the function-scope variable.
       for (auto* member : members_to_clone) {
-        auto member_name = ctx.Clone(member->symbol());
+        auto member_name = ctx.Clone(member->symbol);
         ctx.InsertFront(
-            func->body()->statements(),
+            func->body->statements,
             ctx.dst->Assign(ctx.dst->MemberAccessor(func_var, member_name),
                             ctx.dst->MemberAccessor(new_param, member_name)));
       }
@@ -843,12 +843,12 @@
   /// Process an entry point function.
   /// @param func the entry point function
   void Process(ast::Function* func) {
-    if (func->body()->empty()) {
+    if (func->body->Empty()) {
       return;
     }
 
     // Process entry point parameters.
-    for (auto* param : func->params()) {
+    for (auto* param : func->params) {
       auto* sem = ctx.src->Sem().Get(param);
       if (auto* str = sem->Type()->As<sem::Struct>()) {
         ProcessStructParameter(func, param, str->Declaration());
@@ -885,17 +885,17 @@
 
     // Generate vertex pulling preamble.
     if (auto* block = CreateVertexPullingPreamble()) {
-      ctx.InsertFront(func->body()->statements(), block);
+      ctx.InsertFront(func->body->statements, block);
     }
 
     // Rewrite the function header with the new parameters.
-    auto func_sym = ctx.Clone(func->symbol());
-    auto* ret_type = ctx.Clone(func->return_type());
-    auto* body = ctx.Clone(func->body());
-    auto decos = ctx.Clone(func->decorations());
-    auto ret_decos = ctx.Clone(func->return_type_decorations());
+    auto func_sym = ctx.Clone(func->symbol);
+    auto* ret_type = ctx.Clone(func->return_type);
+    auto* body = ctx.Clone(func->body);
+    auto decos = ctx.Clone(func->decorations);
+    auto ret_decos = ctx.Clone(func->return_type_decorations);
     auto* new_func = ctx.dst->create<ast::Function>(
-        func->source(), func_sym, new_function_parameters, ret_type, body,
+        func->source, func_sym, new_function_parameters, ret_type, body,
         std::move(decos), std::move(ret_decos));
     ctx.Replace(func, new_func);
   }
diff --git a/src/transform/wrap_arrays_in_structs.cc b/src/transform/wrap_arrays_in_structs.cc
index b3c3155..6d6f90c 100644
--- a/src/transform/wrap_arrays_in_structs.cc
+++ b/src/transform/wrap_arrays_in_structs.cc
@@ -60,14 +60,14 @@
   ctx.ReplaceAll([&](ast::ArrayAccessorExpression* accessor)
                      -> ast::ArrayAccessorExpression* {
     if (auto* array = ::tint::As<sem::Array>(
-            sem.Get(accessor->array())->Type()->UnwrapRef())) {
+            sem.Get(accessor->array)->Type()->UnwrapRef())) {
       if (wrapper(array)) {
         // Array is wrapped in a structure. Emit a member accessor to get
         // to the actual array.
-        auto* arr = ctx.Clone(accessor->array());
-        auto* idx = ctx.Clone(accessor->idx_expr());
+        auto* arr = ctx.Clone(accessor->array);
+        auto* idx = ctx.Clone(accessor->index);
         auto* unwrapped = ctx.dst->MemberAccessor(arr, "arr");
-        return ctx.dst->IndexAccessor(accessor->source(), unwrapped, idx);
+        return ctx.dst->IndexAccessor(accessor->source, unwrapped, idx);
       }
     }
     return nullptr;
@@ -80,10 +80,9 @@
       if (auto w = wrapper(array)) {
         // Wrap the array type constructor with another constructor for
         // the wrapper
-        auto* wrapped_array_ty = ctx.Clone(ctor->type());
+        auto* wrapped_array_ty = ctx.Clone(ctor->type);
         auto* array_ty = w.array_type(ctx);
-        auto* arr_ctor =
-            ctx.dst->Construct(array_ty, ctx.Clone(ctor->values()));
+        auto* arr_ctor = ctx.dst->Construct(array_ty, ctx.Clone(ctor->values));
         return ctx.dst->Construct(wrapped_array_ty, arr_ctor);
       }
     }
diff --git a/src/transform/zero_init_workgroup_memory.cc b/src/transform/zero_init_workgroup_memory.cc
index cd3cb55..edd51c3 100644
--- a/src/transform/zero_init_workgroup_memory.cc
+++ b/src/transform/zero_init_workgroup_memory.cc
@@ -116,7 +116,7 @@
     auto& sem = ctx.src->Sem();
 
     CalculateWorkgroupSize(
-        ast::GetDecoration<ast::WorkgroupDecoration>(fn->decorations()));
+        ast::GetDecoration<ast::WorkgroupDecoration>(fn->decorations));
 
     // Generate a list of statements to zero initialize each of the
     // workgroup storage variables used by `fn`. This will populate #statements.
@@ -125,7 +125,7 @@
       if (var->StorageClass() == ast::StorageClass::kWorkgroup) {
         BuildZeroingStatements(
             var->Type()->UnwrapRef(), [&](uint32_t num_values) {
-              auto var_name = ctx.Clone(var->Declaration()->symbol());
+              auto var_name = ctx.Clone(var->Declaration()->symbol);
               return Expression{b.Expr(var_name), num_values, ArrayIndices{}};
             });
       }
@@ -138,11 +138,11 @@
     // Scan the entry point for an existing local_invocation_index builtin
     // parameter
     std::function<ast::Expression*()> local_index;
-    for (auto* param : fn->params()) {
-      if (auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(
-              param->decorations())) {
-        if (builtin->value() == ast::Builtin::kLocalInvocationIndex) {
-          local_index = [=] { return b.Expr(ctx.Clone(param->symbol())); };
+    for (auto* param : fn->params) {
+      if (auto* builtin =
+              ast::GetDecoration<ast::BuiltinDecoration>(param->decorations)) {
+        if (builtin->builtin == ast::Builtin::kLocalInvocationIndex) {
+          local_index = [=] { return b.Expr(ctx.Clone(param->symbol)); };
           break;
         }
       }
@@ -150,11 +150,11 @@
       if (auto* str = sem.Get(param)->Type()->As<sem::Struct>()) {
         for (auto* member : str->Members()) {
           if (auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(
-                  member->Declaration()->decorations())) {
-            if (builtin->value() == ast::Builtin::kLocalInvocationIndex) {
+                  member->Declaration()->decorations)) {
+            if (builtin->builtin == ast::Builtin::kLocalInvocationIndex) {
               local_index = [=] {
-                auto* param_expr = b.Expr(ctx.Clone(param->symbol()));
-                auto member_name = ctx.Clone(member->Declaration()->symbol());
+                auto* param_expr = b.Expr(ctx.Clone(param->symbol));
+                auto member_name = ctx.Clone(member->Declaration()->symbol);
                 return b.MemberAccessor(param_expr, member_name);
               };
               break;
@@ -168,8 +168,8 @@
       auto* param =
           b.Param(b.Symbols().New("local_invocation_index"), b.ty.u32(),
                   {b.Builtin(ast::Builtin::kLocalInvocationIndex)});
-      ctx.InsertBack(fn->params(), param);
-      local_index = [=] { return b.Expr(param->symbol()); };
+      ctx.InsertBack(fn->params, param);
+      local_index = [=] { return b.Expr(param->symbol); };
     }
 
     // Take the zeroing statements and bin them by the number of iterations
@@ -225,7 +225,7 @@
           block.emplace_back(s.stmt);
         }
         auto* for_loop = b.For(init, cond, cont, b.Block(block));
-        ctx.InsertFront(fn->body()->statements(), for_loop);
+        ctx.InsertFront(fn->body->statements, for_loop);
       } else if (num_iterations < workgroup_size_const) {
         // Workgroup size is a known constant, but is greater than
         // num_iterations. Emit an if statement:
@@ -241,7 +241,7 @@
           block.emplace_back(s.stmt);
         }
         auto* if_stmt = b.If(cond, b.Block(block));
-        ctx.InsertFront(fn->body()->statements(), if_stmt);
+        ctx.InsertFront(fn->body->statements, if_stmt);
       } else {
         // Workgroup size exactly equals num_iterations.
         // No need for any conditionals. Just emit a basic block:
@@ -254,12 +254,12 @@
         for (auto& s : stmts) {
           block.emplace_back(s.stmt);
         }
-        ctx.InsertFront(fn->body()->statements(), b.Block(block));
+        ctx.InsertFront(fn->body->statements, b.Block(block));
       }
     }
 
     // Append a single workgroup barrier after the zero initialization.
-    ctx.InsertFront(fn->body()->statements(),
+    ctx.InsertFront(fn->body->statements,
                     b.create<ast::CallStatement>(b.Call("workgroupBarrier")));
   }
 
@@ -294,7 +294,7 @@
 
     if (auto* str = ty->As<sem::Struct>()) {
       for (auto* member : str->Members()) {
-        auto name = ctx.Clone(member->Declaration()->symbol());
+        auto name = ctx.Clone(member->Declaration()->symbol);
         BuildZeroingStatements(member->Type(), [&](uint32_t num_values) {
           auto s = get_expr(num_values);
           return Expression{b.MemberAccessor(s.expr, name), s.num_iterations,
@@ -365,7 +365,7 @@
     bool is_signed = false;
     workgroup_size_const = 1u;
     workgroup_size_expr = nullptr;
-    for (auto* expr : deco->values()) {
+    for (auto* expr : deco->Values()) {
       if (!expr) {
         continue;
       }
@@ -436,7 +436,7 @@
 
 void ZeroInitWorkgroupMemory::Run(CloneContext& ctx, const DataMap&, DataMap&) {
   for (auto* fn : ctx.src->AST().Functions()) {
-    if (fn->pipeline_stage() == ast::PipelineStage::kCompute) {
+    if (fn->PipelineStage() == ast::PipelineStage::kCompute) {
       State{ctx}.Run(fn);
     }
   }
diff --git a/src/writer/append_vector.cc b/src/writer/append_vector.cc
index ea3da7c..0da52c0 100644
--- a/src/writer/append_vector.cc
+++ b/src/writer/append_vector.cc
@@ -80,7 +80,7 @@
   // In that case, preserve the original argument, or you'll get a type error.
   ast::ExpressionList packed;
   if (auto* vc = AsVectorConstructor(b, vector)) {
-    const auto num_supplied = vc->values().size();
+    const auto num_supplied = vc->values.size();
     if (num_supplied == 0) {
       // Zero-value vector constructor. Populate with zeros
       auto buildZero = [&]() -> ast::ScalarConstructorExpression* {
@@ -109,7 +109,7 @@
       }
     } else if (num_supplied + 1 == packed_size) {
       // All vector components were supplied as scalars.  Pass them through.
-      packed = vc->values();
+      packed = vc->values;
     }
   }
   if (packed.empty()) {
diff --git a/src/writer/append_vector_test.cc b/src/writer/append_vector_test.cc
index e720c48..39d837c 100644
--- a/src/writer/append_vector_test.cc
+++ b/src/writer/append_vector_test.cc
@@ -37,10 +37,10 @@
   auto* vec_123 = AppendVector(this, vec_12, scalar_3)
                       ->As<ast::TypeConstructorExpression>();
   ASSERT_NE(vec_123, nullptr);
-  ASSERT_EQ(vec_123->values().size(), 3u);
-  EXPECT_EQ(vec_123->values()[0], scalar_1);
-  EXPECT_EQ(vec_123->values()[1], scalar_2);
-  EXPECT_EQ(vec_123->values()[2], scalar_3);
+  ASSERT_EQ(vec_123->values.size(), 3u);
+  EXPECT_EQ(vec_123->values[0], scalar_1);
+  EXPECT_EQ(vec_123->values[1], scalar_2);
+  EXPECT_EQ(vec_123->values[2], scalar_3);
 }
 
 TEST_F(AppendVectorTest, Vec2i32_u32) {
@@ -56,14 +56,14 @@
   auto* vec_123 = AppendVector(this, vec_12, scalar_3)
                       ->As<ast::TypeConstructorExpression>();
   ASSERT_NE(vec_123, nullptr);
-  ASSERT_EQ(vec_123->values().size(), 3u);
-  EXPECT_EQ(vec_123->values()[0], scalar_1);
-  EXPECT_EQ(vec_123->values()[1], scalar_2);
-  auto* u32_to_i32 = vec_123->values()[2]->As<ast::TypeConstructorExpression>();
+  ASSERT_EQ(vec_123->values.size(), 3u);
+  EXPECT_EQ(vec_123->values[0], scalar_1);
+  EXPECT_EQ(vec_123->values[1], scalar_2);
+  auto* u32_to_i32 = vec_123->values[2]->As<ast::TypeConstructorExpression>();
   ASSERT_NE(u32_to_i32, nullptr);
-  EXPECT_TRUE(u32_to_i32->type()->Is<ast::I32>());
-  ASSERT_EQ(u32_to_i32->values().size(), 1u);
-  EXPECT_EQ(u32_to_i32->values()[0], scalar_3);
+  EXPECT_TRUE(u32_to_i32->type->Is<ast::I32>());
+  ASSERT_EQ(u32_to_i32->values.size(), 1u);
+  EXPECT_EQ(u32_to_i32->values[0], scalar_3);
 }
 
 TEST_F(AppendVectorTest, Vec2i32FromVec2u32_u32) {
@@ -80,22 +80,21 @@
   auto* vec_123 = AppendVector(this, vec_12, scalar_3)
                       ->As<ast::TypeConstructorExpression>();
   ASSERT_NE(vec_123, nullptr);
-  ASSERT_EQ(vec_123->values().size(), 2u);
+  ASSERT_EQ(vec_123->values.size(), 2u);
   auto* v2u32_to_v2i32 =
-      vec_123->values()[0]->As<ast::TypeConstructorExpression>();
+      vec_123->values[0]->As<ast::TypeConstructorExpression>();
   ASSERT_NE(v2u32_to_v2i32, nullptr);
-  ASSERT_TRUE(v2u32_to_v2i32->type()->Is<ast::Vector>());
-  EXPECT_EQ(v2u32_to_v2i32->type()->As<ast::Vector>()->size(), 2u);
-  EXPECT_TRUE(
-      v2u32_to_v2i32->type()->As<ast::Vector>()->type()->Is<ast::I32>());
-  EXPECT_EQ(v2u32_to_v2i32->values().size(), 1u);
-  EXPECT_EQ(v2u32_to_v2i32->values()[0], uvec_12);
+  ASSERT_TRUE(v2u32_to_v2i32->type->Is<ast::Vector>());
+  EXPECT_EQ(v2u32_to_v2i32->type->As<ast::Vector>()->width, 2u);
+  EXPECT_TRUE(v2u32_to_v2i32->type->As<ast::Vector>()->type->Is<ast::I32>());
+  EXPECT_EQ(v2u32_to_v2i32->values.size(), 1u);
+  EXPECT_EQ(v2u32_to_v2i32->values[0], uvec_12);
 
-  auto* u32_to_i32 = vec_123->values()[1]->As<ast::TypeConstructorExpression>();
+  auto* u32_to_i32 = vec_123->values[1]->As<ast::TypeConstructorExpression>();
   ASSERT_NE(u32_to_i32, nullptr);
-  EXPECT_TRUE(u32_to_i32->type()->Is<ast::I32>());
-  ASSERT_EQ(u32_to_i32->values().size(), 1u);
-  EXPECT_EQ(u32_to_i32->values()[0], scalar_3);
+  EXPECT_TRUE(u32_to_i32->type->Is<ast::I32>());
+  ASSERT_EQ(u32_to_i32->values.size(), 1u);
+  EXPECT_EQ(u32_to_i32->values[0], scalar_3);
 }
 
 TEST_F(AppendVectorTest, Vec2i32_f32) {
@@ -111,14 +110,14 @@
   auto* vec_123 = AppendVector(this, vec_12, scalar_3)
                       ->As<ast::TypeConstructorExpression>();
   ASSERT_NE(vec_123, nullptr);
-  ASSERT_EQ(vec_123->values().size(), 3u);
-  EXPECT_EQ(vec_123->values()[0], scalar_1);
-  EXPECT_EQ(vec_123->values()[1], scalar_2);
-  auto* f32_to_i32 = vec_123->values()[2]->As<ast::TypeConstructorExpression>();
+  ASSERT_EQ(vec_123->values.size(), 3u);
+  EXPECT_EQ(vec_123->values[0], scalar_1);
+  EXPECT_EQ(vec_123->values[1], scalar_2);
+  auto* f32_to_i32 = vec_123->values[2]->As<ast::TypeConstructorExpression>();
   ASSERT_NE(f32_to_i32, nullptr);
-  EXPECT_TRUE(f32_to_i32->type()->Is<ast::I32>());
-  ASSERT_EQ(f32_to_i32->values().size(), 1u);
-  EXPECT_EQ(f32_to_i32->values()[0], scalar_3);
+  EXPECT_TRUE(f32_to_i32->type->Is<ast::I32>());
+  ASSERT_EQ(f32_to_i32->values.size(), 1u);
+  EXPECT_EQ(f32_to_i32->values[0], scalar_3);
 }
 
 TEST_F(AppendVectorTest, Vec3i32_i32) {
@@ -135,11 +134,11 @@
   auto* vec_1234 = AppendVector(this, vec_123, scalar_4)
                        ->As<ast::TypeConstructorExpression>();
   ASSERT_NE(vec_1234, nullptr);
-  ASSERT_EQ(vec_1234->values().size(), 4u);
-  EXPECT_EQ(vec_1234->values()[0], scalar_1);
-  EXPECT_EQ(vec_1234->values()[1], scalar_2);
-  EXPECT_EQ(vec_1234->values()[2], scalar_3);
-  EXPECT_EQ(vec_1234->values()[3], scalar_4);
+  ASSERT_EQ(vec_1234->values.size(), 4u);
+  EXPECT_EQ(vec_1234->values[0], scalar_1);
+  EXPECT_EQ(vec_1234->values[1], scalar_2);
+  EXPECT_EQ(vec_1234->values[2], scalar_3);
+  EXPECT_EQ(vec_1234->values[3], scalar_4);
 }
 
 TEST_F(AppendVectorTest, Vec2i32Var_i32) {
@@ -154,9 +153,9 @@
   auto* vec_123 = AppendVector(this, vec_12, scalar_3)
                       ->As<ast::TypeConstructorExpression>();
   ASSERT_NE(vec_123, nullptr);
-  ASSERT_EQ(vec_123->values().size(), 2u);
-  EXPECT_EQ(vec_123->values()[0], vec_12);
-  EXPECT_EQ(vec_123->values()[1], scalar_3);
+  ASSERT_EQ(vec_123->values.size(), 2u);
+  EXPECT_EQ(vec_123->values[0], vec_12);
+  EXPECT_EQ(vec_123->values[1], scalar_3);
 }
 
 TEST_F(AppendVectorTest, Vec2i32_i32Var) {
@@ -173,10 +172,10 @@
   auto* vec_123 = AppendVector(this, vec_12, scalar_3)
                       ->As<ast::TypeConstructorExpression>();
   ASSERT_NE(vec_123, nullptr);
-  ASSERT_EQ(vec_123->values().size(), 3u);
-  EXPECT_EQ(vec_123->values()[0], scalar_1);
-  EXPECT_EQ(vec_123->values()[1], scalar_2);
-  EXPECT_EQ(vec_123->values()[2], scalar_3);
+  ASSERT_EQ(vec_123->values.size(), 3u);
+  EXPECT_EQ(vec_123->values[0], scalar_1);
+  EXPECT_EQ(vec_123->values[1], scalar_2);
+  EXPECT_EQ(vec_123->values[2], scalar_3);
 }
 
 TEST_F(AppendVectorTest, Vec2i32Var_i32Var) {
@@ -192,9 +191,9 @@
   auto* vec_123 = AppendVector(this, vec_12, scalar_3)
                       ->As<ast::TypeConstructorExpression>();
   ASSERT_NE(vec_123, nullptr);
-  ASSERT_EQ(vec_123->values().size(), 2u);
-  EXPECT_EQ(vec_123->values()[0], vec_12);
-  EXPECT_EQ(vec_123->values()[1], scalar_3);
+  ASSERT_EQ(vec_123->values.size(), 2u);
+  EXPECT_EQ(vec_123->values[0], vec_12);
+  EXPECT_EQ(vec_123->values[1], scalar_3);
 }
 
 TEST_F(AppendVectorTest, Vec2i32Var_f32Var) {
@@ -210,13 +209,13 @@
   auto* vec_123 = AppendVector(this, vec_12, scalar_3)
                       ->As<ast::TypeConstructorExpression>();
   ASSERT_NE(vec_123, nullptr);
-  ASSERT_EQ(vec_123->values().size(), 2u);
-  EXPECT_EQ(vec_123->values()[0], vec_12);
-  auto* f32_to_i32 = vec_123->values()[1]->As<ast::TypeConstructorExpression>();
+  ASSERT_EQ(vec_123->values.size(), 2u);
+  EXPECT_EQ(vec_123->values[0], vec_12);
+  auto* f32_to_i32 = vec_123->values[1]->As<ast::TypeConstructorExpression>();
   ASSERT_NE(f32_to_i32, nullptr);
-  EXPECT_TRUE(f32_to_i32->type()->Is<ast::I32>());
-  ASSERT_EQ(f32_to_i32->values().size(), 1u);
-  EXPECT_EQ(f32_to_i32->values()[0], scalar_3);
+  EXPECT_TRUE(f32_to_i32->type->Is<ast::I32>());
+  ASSERT_EQ(f32_to_i32->values.size(), 1u);
+  EXPECT_EQ(f32_to_i32->values[0], scalar_3);
 }
 
 TEST_F(AppendVectorTest, Vec2boolVar_boolVar) {
@@ -232,9 +231,9 @@
   auto* vec_123 = AppendVector(this, vec_12, scalar_3)
                       ->As<ast::TypeConstructorExpression>();
   ASSERT_NE(vec_123, nullptr);
-  ASSERT_EQ(vec_123->values().size(), 2u);
-  EXPECT_EQ(vec_123->values()[0], vec_12);
-  EXPECT_EQ(vec_123->values()[1], scalar_3);
+  ASSERT_EQ(vec_123->values.size(), 2u);
+  EXPECT_EQ(vec_123->values[0], vec_12);
+  EXPECT_EQ(vec_123->values[1], scalar_3);
 }
 
 TEST_F(AppendVectorTest, ZeroVec3i32_i32) {
@@ -248,15 +247,15 @@
   auto* vec_0004 =
       AppendVector(this, vec000, scalar)->As<ast::TypeConstructorExpression>();
   ASSERT_NE(vec_0004, nullptr);
-  ASSERT_EQ(vec_0004->values().size(), 4u);
+  ASSERT_EQ(vec_0004->values.size(), 4u);
   for (size_t i = 0; i < 3; i++) {
-    auto* ctor = vec_0004->values()[i]->As<ast::ScalarConstructorExpression>();
+    auto* ctor = vec_0004->values[i]->As<ast::ScalarConstructorExpression>();
     ASSERT_NE(ctor, nullptr);
-    auto* literal = As<ast::SintLiteral>(ctor->literal());
+    auto* literal = As<ast::SintLiteral>(ctor->literal);
     ASSERT_NE(literal, nullptr);
-    EXPECT_EQ(literal->value(), 0);
+    EXPECT_EQ(literal->value, 0);
   }
-  EXPECT_EQ(vec_0004->values()[3], scalar);
+  EXPECT_EQ(vec_0004->values[3], scalar);
 }
 
 }  // namespace
diff --git a/src/writer/glsl/generator.cc b/src/writer/glsl/generator.cc
index a03e7ca..101b7ba 100644
--- a/src/writer/glsl/generator.cc
+++ b/src/writer/glsl/generator.cc
@@ -50,8 +50,8 @@
   // Collect the list of entry points in the sanitized program.
   for (auto* func : output.program.AST().Functions()) {
     if (func->IsEntryPoint()) {
-      auto name = output.program.Symbols().NameFor(func->symbol());
-      result.entry_points.push_back({name, func->pipeline_stage()});
+      auto name = output.program.Symbols().NameFor(func->symbol);
+      result.entry_points.push_back({name, func->PipelineStage()});
     }
   }
 
diff --git a/src/writer/glsl/generator_impl.cc b/src/writer/glsl/generator_impl.cc
index 54aa31e..c5a8aa0 100644
--- a/src/writer/glsl/generator_impl.cc
+++ b/src/writer/glsl/generator_impl.cc
@@ -59,12 +59,7 @@
 const char kSpecConstantPrefix[] = "WGSL_SPEC_CONSTANT_";
 
 bool last_is_break_or_fallthrough(const ast::BlockStatement* stmts) {
-  if (stmts->empty()) {
-    return false;
-  }
-
-  return stmts->last()->Is<ast::BreakStatement>() ||
-         stmts->last()->Is<ast::FallthroughStatement>();
+  return IsAnyOf<ast::BreakStatement, ast::FallthroughStatement>(stmts->Last());
 }
 
 const char* image_format_to_rwtexture_type(ast::ImageFormat image_format) {
@@ -164,12 +159,12 @@
 
 bool GeneratorImpl::EmitArrayAccessor(std::ostream& out,
                                       ast::ArrayAccessorExpression* expr) {
-  if (!EmitExpression(out, expr->array())) {
+  if (!EmitExpression(out, expr->array)) {
     return false;
   }
   out << "[";
 
-  if (!EmitExpression(out, expr->idx_expr())) {
+  if (!EmitExpression(out, expr->index)) {
     return false;
   }
   out << "]";
@@ -196,7 +191,7 @@
     return false;
   }
   out << "(";
-  if (!EmitExpression(out, expr->expr())) {
+  if (!EmitExpression(out, expr->expr)) {
     return false;
   }
   out << ")";
@@ -205,11 +200,11 @@
 
 bool GeneratorImpl::EmitAssign(ast::AssignmentStatement* stmt) {
   auto out = line();
-  if (!EmitExpression(out, stmt->lhs())) {
+  if (!EmitExpression(out, stmt->lhs)) {
     return false;
   }
   out << " = ";
-  if (!EmitExpression(out, stmt->rhs())) {
+  if (!EmitExpression(out, stmt->rhs)) {
     return false;
   }
   out << ";";
@@ -217,20 +212,20 @@
 }
 
 bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) {
-  if (expr->op() == ast::BinaryOp::kLogicalAnd ||
-      expr->op() == ast::BinaryOp::kLogicalOr) {
+  if (expr->op == ast::BinaryOp::kLogicalAnd ||
+      expr->op == ast::BinaryOp::kLogicalOr) {
     auto name = UniqueIdentifier(kTempNamePrefix);
 
     {
       auto pre = line();
       pre << "bool " << name << " = ";
-      if (!EmitExpression(pre, expr->lhs())) {
+      if (!EmitExpression(pre, expr->lhs)) {
         return false;
       }
       pre << ";";
     }
 
-    if (expr->op() == ast::BinaryOp::kLogicalOr) {
+    if (expr->op == ast::BinaryOp::kLogicalOr) {
       line() << "if (!" << name << ") {";
     } else {
       line() << "if (" << name << ") {";
@@ -240,7 +235,7 @@
       ScopedIndent si(this);
       auto pre = line();
       pre << name << " = ";
-      if (!EmitExpression(pre, expr->rhs())) {
+      if (!EmitExpression(pre, expr->rhs)) {
         return false;
       }
       pre << ";";
@@ -253,12 +248,12 @@
   }
 
   out << "(";
-  if (!EmitExpression(out, expr->lhs())) {
+  if (!EmitExpression(out, expr->lhs)) {
     return false;
   }
   out << " ";
 
-  switch (expr->op()) {
+  switch (expr->op) {
     case ast::BinaryOp::kAnd:
       out << "&";
       break;
@@ -325,7 +320,7 @@
   }
   out << " ";
 
-  if (!EmitExpression(out, expr->rhs())) {
+  if (!EmitExpression(out, expr->rhs)) {
     return false;
   }
 
@@ -349,7 +344,7 @@
 
 bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
   line() << "{";
-  if (!EmitStatementsWithIndent(stmt->statements())) {
+  if (!EmitStatementsWithIndent(stmt->statements)) {
     return false;
   }
   line() << "}";
@@ -362,15 +357,15 @@
 }
 
 bool GeneratorImpl::EmitCall(std::ostream& out, ast::CallExpression* expr) {
-  const auto& args = expr->args();
-  auto* ident = expr->func();
+  const auto& args = expr->args;
+  auto* ident = expr->func;
   auto* call = builder_.Sem().Get(expr);
   auto* target = call->Target();
 
   if (auto* func = target->As<sem::Function>()) {
     if (ast::HasDecoration<
             transform::CalculateArrayLength::BufferSizeIntrinsic>(
-            func->Declaration()->decorations())) {
+            func->Declaration()->decorations)) {
       // Special function generated by the CalculateArrayLength transform for
       // calling X.GetDimensions(Y)
       if (!EmitExpression(out, args[0])) {
@@ -397,7 +392,7 @@
     } else if (intrinsic->Type() == sem::IntrinsicType::kIsNormal) {
       return EmitIsNormalCall(out, expr, intrinsic);
     } else if (intrinsic->Type() == sem::IntrinsicType::kIgnore) {
-      return EmitExpression(out, expr->args()[0]);
+      return EmitExpression(out, expr->args[0]);
     } else if (intrinsic->IsDataPacking()) {
       return EmitDataPackingCall(out, expr, intrinsic);
     } else if (intrinsic->IsDataUnpacking()) {
@@ -430,14 +425,14 @@
     return true;
   }
 
-  auto name = builder_.Symbols().NameFor(ident->symbol());
-  auto caller_sym = ident->symbol();
+  auto name = builder_.Symbols().NameFor(ident->symbol);
+  auto caller_sym = ident->symbol;
 
-  auto* func = builder_.AST().Functions().Find(ident->symbol());
+  auto* func = builder_.AST().Functions().Find(ident->symbol);
   if (func == nullptr) {
     diagnostics_.add_error(diag::System::Writer,
                            "Unable to find function: " +
-                               builder_.Symbols().NameFor(ident->symbol()));
+                               builder_.Symbols().NameFor(ident->symbol));
     return false;
   }
 
@@ -484,8 +479,8 @@
 
     {
       ScopedParen sp(pre);
-      for (size_t i = 0; i < expr->args().size(); i++) {
-        auto* arg = expr->args()[i];
+      for (size_t i = 0; i < expr->args.size(); i++) {
+        auto* arg = expr->args[i];
         if (i > 0) {
           pre << ", ";
         }
@@ -511,7 +506,7 @@
       pre << "InterlockedOr";
       {
         ScopedParen sp(pre);
-        if (!EmitExpression(pre, expr->args()[0])) {
+        if (!EmitExpression(pre, expr->args[0])) {
           return false;
         }
         pre << ", 0, " << result;
@@ -541,11 +536,11 @@
       out << "InterlockedExchange";
       {
         ScopedParen sp(out);
-        if (!EmitExpression(out, expr->args()[0])) {
+        if (!EmitExpression(out, expr->args[0])) {
           return false;
         }
         out << ", ";
-        if (!EmitExpression(out, expr->args()[1])) {
+        if (!EmitExpression(out, expr->args[1])) {
           return false;
         }
         out << ", " << result;
@@ -553,9 +548,9 @@
       return true;
     }
     case sem::IntrinsicType::kAtomicCompareExchangeWeak: {
-      auto* dest = expr->args()[0];
-      auto* compare_value = expr->args()[1];
-      auto* value = expr->args()[2];
+      auto* dest = expr->args[0];
+      auto* compare_value = expr->args[1];
+      auto* value = expr->args[2];
 
       std::string compare = UniqueIdentifier("atomic_compare_value");
 
@@ -631,9 +626,9 @@
 
 bool GeneratorImpl::EmitSelectCall(std::ostream& out,
                                    ast::CallExpression* expr) {
-  auto* expr_false = expr->args()[0];
-  auto* expr_true = expr->args()[1];
-  auto* expr_cond = expr->args()[2];
+  auto* expr_false = expr->args[0];
+  auto* expr_true = expr->args[1];
+  auto* expr_cond = expr->args[2];
   ScopedParen paren(out);
   if (!EmitExpression(out, expr_cond)) {
     return false;
@@ -657,7 +652,7 @@
 bool GeneratorImpl::EmitModfCall(std::ostream& out,
                                  ast::CallExpression* expr,
                                  const sem::Intrinsic* intrinsic) {
-  if (expr->args().size() == 1) {
+  if (expr->args.size() == 1) {
     return CallIntrinsicHelper(
         out, expr, intrinsic,
         [&](TextBuffer* b, const std::vector<std::string>& params) {
@@ -694,11 +689,11 @@
   // DEPRECATED
   out << "modf";
   ScopedParen sp(out);
-  if (!EmitExpression(out, expr->args()[0])) {
+  if (!EmitExpression(out, expr->args[0])) {
     return false;
   }
   out << ", ";
-  if (!EmitExpression(out, expr->args()[1])) {
+  if (!EmitExpression(out, expr->args[1])) {
     return false;
   }
   return true;
@@ -707,7 +702,7 @@
 bool GeneratorImpl::EmitFrexpCall(std::ostream& out,
                                   ast::CallExpression* expr,
                                   const sem::Intrinsic* intrinsic) {
-  if (expr->args().size() == 1) {
+  if (expr->args.size() == 1) {
     return CallIntrinsicHelper(
         out, expr, intrinsic,
         [&](TextBuffer* b, const std::vector<std::string>& params) {
@@ -961,7 +956,7 @@
   using Usage = sem::ParameterUsage;
 
   auto& signature = intrinsic->Signature();
-  auto arguments = expr->args();
+  auto arguments = expr->args;
 
   // Returns the argument with the given usage
   auto arg = [&](Usage usage) {
@@ -1261,14 +1256,14 @@
   if (stmt->IsDefault()) {
     line() << "default: {";
   } else {
-    for (auto* selector : stmt->selectors()) {
+    for (auto* selector : stmt->selectors) {
       auto out = line();
       out << "case ";
       if (!EmitLiteral(out, selector)) {
         return false;
       }
       out << ":";
-      if (selector == stmt->selectors().back()) {
+      if (selector == stmt->selectors.back()) {
         out << " {";
       }
     }
@@ -1276,10 +1271,10 @@
 
   {
     ScopedIndent si(this);
-    if (!EmitStatements(stmt->body()->statements())) {
+    if (!EmitStatements(stmt->body->statements)) {
       return false;
     }
-    if (!last_is_break_or_fallthrough(stmt->body())) {
+    if (!last_is_break_or_fallthrough(stmt->body)) {
       line() << "break;";
     }
   }
@@ -1300,7 +1295,7 @@
 bool GeneratorImpl::EmitScalarConstructor(
     std::ostream& out,
     ast::ScalarConstructorExpression* expr) {
-  return EmitLiteral(out, expr->literal());
+  return EmitLiteral(out, expr->literal);
 }
 
 bool GeneratorImpl::EmitTypeConstructor(std::ostream& out,
@@ -1309,15 +1304,15 @@
 
   // If the type constructor is empty then we need to construct with the zero
   // value for all components.
-  if (expr->values().empty()) {
+  if (expr->values.empty()) {
     return EmitZeroValue(out, type);
   }
 
   // For single-value vector initializers, swizzle the scalar to the right
   // vector dimension using .x
   const bool is_single_value_vector_init =
-      type->is_scalar_vector() && expr->values().size() == 1 &&
-      TypeOf(expr->values()[0])->UnwrapRef()->is_scalar();
+      type->is_scalar_vector() && expr->values.size() == 1 &&
+      TypeOf(expr->values[0])->UnwrapRef()->is_scalar();
 
   auto it = structure_builders_.find(As<sem::Struct>(type));
   if (it != structure_builders_.end()) {
@@ -1335,7 +1330,7 @@
   }
 
   bool first = true;
-  for (auto* e : expr->values()) {
+  for (auto* e : expr->values) {
     if (!first) {
       out << ", ";
     }
@@ -1403,7 +1398,7 @@
 
 bool GeneratorImpl::EmitIdentifier(std::ostream& out,
                                    ast::IdentifierExpression* expr) {
-  out << builder_.Symbols().NameFor(expr->symbol());
+  out << builder_.Symbols().NameFor(expr->symbol);
   return true;
 }
 
@@ -1411,25 +1406,25 @@
   {
     auto out = line();
     out << "if (";
-    if (!EmitExpression(out, stmt->condition())) {
+    if (!EmitExpression(out, stmt->condition)) {
       return false;
     }
     out << ") {";
   }
 
-  if (!EmitStatementsWithIndent(stmt->body()->statements())) {
+  if (!EmitStatementsWithIndent(stmt->body->statements)) {
     return false;
   }
 
-  for (auto* e : stmt->else_statements()) {
-    if (e->HasCondition()) {
+  for (auto* e : stmt->else_statements) {
+    if (e->condition) {
       line() << "} else {";
       increment_indent();
 
       {
         auto out = line();
         out << "if (";
-        if (!EmitExpression(out, e->condition())) {
+        if (!EmitExpression(out, e->condition)) {
           return false;
         }
         out << ") {";
@@ -1438,15 +1433,15 @@
       line() << "} else {";
     }
 
-    if (!EmitStatementsWithIndent(e->body()->statements())) {
+    if (!EmitStatementsWithIndent(e->body->statements)) {
       return false;
     }
   }
 
   line() << "}";
 
-  for (auto* e : stmt->else_statements()) {
-    if (e->HasCondition()) {
+  for (auto* e : stmt->else_statements) {
+    if (e->condition) {
       decrement_indent();
       line() << "}";
     }
@@ -1457,14 +1452,14 @@
 bool GeneratorImpl::EmitFunction(ast::Function* func) {
   auto* sem = builder_.Sem().Get(func);
 
-  if (ast::HasDecoration<ast::InternalDecoration>(func->decorations())) {
+  if (ast::HasDecoration<ast::InternalDecoration>(func->decorations)) {
     // An internal function. Do not emit.
     return true;
   }
 
   {
     auto out = line();
-    auto name = builder_.Symbols().NameFor(func->symbol());
+    auto name = builder_.Symbols().NameFor(func->symbol);
     // If the function returns an array, then we need to declare a typedef for
     // this.
     if (sem->ReturnType()->Is<sem::Array>()) {
@@ -1513,14 +1508,14 @@
       // storage buffers and a uint4[N] for uniform buffers.
       if (!EmitTypeAndName(
               out, type, v->StorageClass(), v->Access(),
-              builder_.Symbols().NameFor(v->Declaration()->symbol()))) {
+              builder_.Symbols().NameFor(v->Declaration()->symbol))) {
         return false;
       }
     }
     out << ") {";
   }
 
-  if (!EmitStatementsWithIndent(func->body()->statements())) {
+  if (!EmitStatementsWithIndent(func->body->statements)) {
     return false;
   }
 
@@ -1530,7 +1525,7 @@
 }
 
 bool GeneratorImpl::EmitGlobalVariable(ast::Variable* global) {
-  if (global->is_const()) {
+  if (global->is_const) {
     return EmitProgramConstVariable(global);
   }
 
@@ -1560,7 +1555,7 @@
   auto* type = var->Type()->UnwrapRef();
   auto out = line();
   if (!EmitTypeAndName(out, type, ast::StorageClass::kUniform, var->Access(),
-                       builder_.Symbols().NameFor(decl->symbol()))) {
+                       builder_.Symbols().NameFor(decl->symbol))) {
     return false;
   }
   out << ";";
@@ -1573,7 +1568,7 @@
   auto* type = var->Type()->UnwrapRef();
   auto out = line();
   if (!EmitTypeAndName(out, type, ast::StorageClass::kStorage, var->Access(),
-                       builder_.Symbols().NameFor(decl->symbol()))) {
+                       builder_.Symbols().NameFor(decl->symbol))) {
     return false;
   }
 
@@ -1586,7 +1581,7 @@
   auto* decl = var->Declaration();
   auto out = line();
 
-  auto name = builder_.Symbols().NameFor(decl->symbol());
+  auto name = builder_.Symbols().NameFor(decl->symbol);
   auto* type = var->Type()->UnwrapRef();
   if (!EmitTypeAndName(out, type, var->StorageClass(), var->Access(), name)) {
     return false;
@@ -1600,14 +1595,14 @@
   auto* decl = var->Declaration();
   auto out = line();
 
-  auto name = builder_.Symbols().NameFor(decl->symbol());
+  auto name = builder_.Symbols().NameFor(decl->symbol);
   auto* type = var->Type()->UnwrapRef();
   if (!EmitTypeAndName(out, type, var->StorageClass(), var->Access(), name)) {
     return false;
   }
 
   out << " = ";
-  if (auto* constructor = decl->constructor()) {
+  if (auto* constructor = decl->constructor) {
     if (!EmitExpression(out, constructor)) {
       return false;
     }
@@ -1627,13 +1622,13 @@
 
   out << "groupshared ";
 
-  auto name = builder_.Symbols().NameFor(decl->symbol());
+  auto name = builder_.Symbols().NameFor(decl->symbol);
   auto* type = var->Type()->UnwrapRef();
   if (!EmitTypeAndName(out, type, var->StorageClass(), var->Access(), name)) {
     return false;
   }
 
-  if (auto* constructor = decl->constructor()) {
+  if (auto* constructor = decl->constructor) {
     out << " = ";
     if (!EmitExpression(out, constructor)) {
       return false;
@@ -1739,7 +1734,7 @@
 
   {
     auto out = line();
-    if (func->pipeline_stage() == ast::PipelineStage::kCompute) {
+    if (func->PipelineStage() == ast::PipelineStage::kCompute) {
       // Emit the layout(local_size) attributes.
       auto wgsize = func_sem->workgroup_size();
       out << "layout(";
@@ -1764,14 +1759,14 @@
       out << ") in;" << std::endl;
     }
 
-    out << func->return_type()->FriendlyName(builder_.Symbols());
+    out << func->return_type->FriendlyName(builder_.Symbols());
 
-    out << " " << builder_.Symbols().NameFor(func->symbol()) << "(";
+    out << " " << builder_.Symbols().NameFor(func->symbol) << "(";
 
     bool first = true;
 
     // Emit entry point parameters.
-    for (auto* var : func->params()) {
+    for (auto* var : func->params) {
       auto* sem = builder_.Sem().Get(var);
       auto* type = sem->Type();
       if (!type->Is<sem::Struct>()) {
@@ -1787,7 +1782,7 @@
       first = false;
 
       if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(),
-                           builder_.Symbols().NameFor(var->symbol()))) {
+                           builder_.Symbols().NameFor(var->symbol))) {
         return false;
       }
     }
@@ -1798,11 +1793,11 @@
   {
     ScopedIndent si(this);
 
-    if (!EmitStatements(func->body()->statements())) {
+    if (!EmitStatements(func->body->statements)) {
       return false;
     }
 
-    if (!Is<ast::ReturnStatement>(func->get_last_statement())) {
+    if (!Is<ast::ReturnStatement>(func->body->Last())) {
       ast::ReturnStatement ret(ProgramID(), Source{});
       if (!EmitStatement(&ret)) {
         return false;
@@ -1815,18 +1810,18 @@
   auto out = line();
 
   // Declare entry point input variables
-  for (auto* var : func->params()) {
+  for (auto* var : func->params) {
     auto* sem = builder_.Sem().Get(var);
     auto* str = sem->Type()->As<sem::Struct>();
     for (auto* member : str->Members()) {
       if (ast::HasDecoration<ast::BuiltinDecoration>(
-              member->Declaration()->decorations())) {
+              member->Declaration()->decorations)) {
         continue;
       }
       if (!EmitTypeAndName(
               out, member->Type(), ast::StorageClass::kInput,
               ast::Access::kReadWrite,
-              builder_.Symbols().NameFor(member->Declaration()->symbol()))) {
+              builder_.Symbols().NameFor(member->Declaration()->symbol))) {
         return false;
       }
       out << ";" << std::endl;
@@ -1838,13 +1833,13 @@
   if (return_type) {
     for (auto* member : return_type->Members()) {
       if (ast::HasDecoration<ast::BuiltinDecoration>(
-              member->Declaration()->decorations())) {
+              member->Declaration()->decorations)) {
         continue;
       }
       if (!EmitTypeAndName(
               out, member->Type(), ast::StorageClass::kOutput,
               ast::Access::kReadWrite,
-              builder_.Symbols().NameFor(member->Declaration()->symbol()))) {
+              builder_.Symbols().NameFor(member->Declaration()->symbol))) {
         return false;
       }
       out << ";" << std::endl;
@@ -1854,7 +1849,7 @@
   // Create a main() function which calls the entry point.
   out << "void main() {" << std::endl;
   std::string printed_name;
-  for (auto* var : func->params()) {
+  for (auto* var : func->params) {
     out << "  ";
     auto* sem = builder_.Sem().Get(var);
     if (!EmitTypeAndName(out, sem->Type(), sem->StorageClass(), sem->Access(),
@@ -1866,20 +1861,20 @@
     auto* str = type->As<sem::Struct>();
     for (auto* member : str->Members()) {
       std::string name =
-          builder_.Symbols().NameFor(member->Declaration()->symbol());
+          builder_.Symbols().NameFor(member->Declaration()->symbol);
       out << "  inputs." << name << " = ";
       if (auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(
-              member->Declaration()->decorations())) {
-        if (builtin_type(builtin->value()) != member->Type()) {
+              member->Declaration()->decorations)) {
+        if (builtin_type(builtin->builtin) != member->Type()) {
           if (!EmitType(out, member->Type(), ast::StorageClass::kNone,
                         ast::Access::kReadWrite, "")) {
             return false;
           }
           out << "(";
-          out << builtin_to_string(builtin->value());
+          out << builtin_to_string(builtin->builtin);
           out << ")";
         } else {
-          out << builtin_to_string(builtin->value());
+          out << builtin_to_string(builtin->builtin);
         }
       } else {
         out << name;
@@ -1893,8 +1888,8 @@
         << "outputs;" << std::endl;
     out << "  outputs = ";
   }
-  out << builder_.Symbols().NameFor(func->symbol());
-  if (func->params().empty()) {
+  out << builder_.Symbols().NameFor(func->symbol);
+  if (func->params.empty()) {
     out << "()";
   } else {
     out << "(inputs)";
@@ -1905,11 +1900,11 @@
   if (str) {
     for (auto* member : str->Members()) {
       std::string name =
-          builder_.Symbols().NameFor(member->Declaration()->symbol());
+          builder_.Symbols().NameFor(member->Declaration()->symbol);
       out << "  ";
       if (auto* builtin = ast::GetDecoration<ast::BuiltinDecoration>(
-              member->Declaration()->decorations())) {
-        out << builtin_to_string(builtin->value());
+              member->Declaration()->decorations)) {
+        out << builtin_to_string(builtin->builtin);
       } else {
         out << name;
       }
@@ -1924,20 +1919,19 @@
 
 bool GeneratorImpl::EmitLiteral(std::ostream& out, ast::Literal* lit) {
   if (auto* l = lit->As<ast::BoolLiteral>()) {
-    out << (l->IsTrue() ? "true" : "false");
+    out << (l->value ? "true" : "false");
   } else if (auto* fl = lit->As<ast::FloatLiteral>()) {
-    if (std::isinf(fl->value())) {
-      out << (fl->value() >= 0 ? "asfloat(0x7f800000u)"
-                               : "asfloat(0xff800000u)");
-    } else if (std::isnan(fl->value())) {
+    if (std::isinf(fl->value)) {
+      out << (fl->value >= 0 ? "asfloat(0x7f800000u)" : "asfloat(0xff800000u)");
+    } else if (std::isnan(fl->value)) {
       out << "asfloat(0x7fc00000u)";
     } else {
-      out << FloatToString(fl->value()) << "f";
+      out << FloatToString(fl->value) << "f";
     }
   } else if (auto* sl = lit->As<ast::SintLiteral>()) {
-    out << sl->value();
+    out << sl->value;
   } else if (auto* ul = lit->As<ast::UintLiteral>()) {
-    out << ul->value() << "u";
+    out << ul->value << "u";
   } else {
     diagnostics_.add_error(diag::System::Writer, "unknown literal type");
     return false;
@@ -2022,8 +2016,8 @@
 
 bool GeneratorImpl::EmitLoop(ast::LoopStatement* stmt) {
   auto emit_continuing = [this, stmt]() {
-    if (stmt->has_continuing()) {
-      if (!EmitBlock(stmt->continuing())) {
+    if (stmt->continuing && !stmt->continuing->Empty()) {
+      if (!EmitBlock(stmt->continuing)) {
         return false;
       }
     }
@@ -2034,7 +2028,7 @@
   line() << "while (true) {";
   {
     ScopedIndent si(this);
-    if (!EmitStatements(stmt->body()->statements())) {
+    if (!EmitStatements(stmt->body->statements)) {
       return false;
     }
     if (!emit_continuing()) {
@@ -2057,7 +2051,7 @@
   });
 
   TextBuffer init_buf;
-  if (auto* init = stmt->initializer()) {
+  if (auto* init = stmt->initializer) {
     TINT_SCOPED_ASSIGNMENT(current_buffer_, &init_buf);
     if (!EmitStatement(init)) {
       return false;
@@ -2066,7 +2060,7 @@
 
   TextBuffer cond_pre;
   std::stringstream cond_buf;
-  if (auto* cond = stmt->condition()) {
+  if (auto* cond = stmt->condition) {
     TINT_SCOPED_ASSIGNMENT(current_buffer_, &cond_pre);
     if (!EmitExpression(cond_buf, cond)) {
       return false;
@@ -2074,7 +2068,7 @@
   }
 
   TextBuffer cont_buf;
-  if (auto* cont = stmt->continuing()) {
+  if (auto* cont = stmt->continuing) {
     TINT_SCOPED_ASSIGNMENT(current_buffer_, &cont_buf);
     if (!EmitStatement(cont)) {
       return false;
@@ -2089,7 +2083,7 @@
   // If the for-loop has multi-statement initializer, or is going to be emitted
   // as a `while(true)` loop, then declare the initializer statement(s) before
   // the loop.
-  if (init_buf.lines.size() > 1 || (stmt->initializer() && emit_as_loop)) {
+  if (init_buf.lines.size() > 1 || (stmt->initializer && emit_as_loop)) {
     current_buffer_->Append(init_buf);
     init_buf.lines.clear();  // Don't emit the initializer again in the 'for'
   }
@@ -2108,12 +2102,12 @@
       line() << "}";
     });
 
-    if (stmt->condition()) {
+    if (stmt->condition) {
       current_buffer_->Append(cond_pre);
       line() << "if (!(" << cond_buf.str() << ")) { break; }";
     }
 
-    if (!EmitStatements(stmt->body()->statements())) {
+    if (!EmitStatements(stmt->body->statements)) {
       return false;
     }
 
@@ -2145,7 +2139,7 @@
     {
       auto emit_continuing = [] { return true; };
       TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
-      if (!EmitStatementsWithIndent(stmt->body()->statements())) {
+      if (!EmitStatementsWithIndent(stmt->body->statements)) {
         return false;
       }
     }
@@ -2157,15 +2151,15 @@
 
 bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
                                        ast::MemberAccessorExpression* expr) {
-  if (!EmitExpression(out, expr->structure())) {
+  if (!EmitExpression(out, expr->structure)) {
     return false;
   }
   out << ".";
 
   // Swizzles output the name directly
   if (builder_.Sem().Get(expr)->Is<sem::Swizzle>()) {
-    out << builder_.Symbols().NameFor(expr->member()->symbol());
-  } else if (!EmitExpression(out, expr->member())) {
+    out << builder_.Symbols().NameFor(expr->member->symbol);
+  } else if (!EmitExpression(out, expr->member)) {
     return false;
   }
 
@@ -2173,10 +2167,10 @@
 }
 
 bool GeneratorImpl::EmitReturn(ast::ReturnStatement* stmt) {
-  if (stmt->has_value()) {
+  if (stmt->value) {
     auto out = line();
     out << "return ";
-    if (!EmitExpression(out, stmt->value())) {
+    if (!EmitExpression(out, stmt->value)) {
       return false;
     }
     out << ";";
@@ -2198,10 +2192,10 @@
   }
   if (auto* c = stmt->As<ast::CallStatement>()) {
     auto out = line();
-    if (!TypeOf(c->expr())->Is<sem::Void>()) {
+    if (!TypeOf(c->expr)->Is<sem::Void>()) {
       out << "(void) ";
     }
-    if (!EmitCall(out, c->expr())) {
+    if (!EmitCall(out, c->expr)) {
       return false;
     }
     out << ";";
@@ -2233,7 +2227,7 @@
     return EmitSwitch(s);
   }
   if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
-    return EmitVariable(v->variable());
+    return EmitVariable(v->variable);
   }
 
   diagnostics_.add_error(
@@ -2246,7 +2240,7 @@
   {  // switch(expr) {
     auto out = line();
     out << "switch(";
-    if (!EmitExpression(out, stmt->condition())) {
+    if (!EmitExpression(out, stmt->condition)) {
       return false;
     }
     out << ") {";
@@ -2254,7 +2248,7 @@
 
   {
     ScopedIndent si(this);
-    for (auto* s : stmt->body()) {
+    for (auto* s : stmt->body) {
       if (!EmitCase(s)) {
         return false;
       }
@@ -2476,7 +2470,7 @@
       std::string pre, post;
 
       if (auto* decl = mem->Declaration()) {
-        for (auto* deco : decl->decorations()) {
+        for (auto* deco : decl->decorations) {
           if (deco->As<ast::LocationDecoration>()) {
             auto& pipeline_stage_uses = str->PipelineStageUses();
             if (pipeline_stage_uses.size() != 1) {
@@ -2485,8 +2479,8 @@
             }
           } else if (auto* interpolate =
                          deco->As<ast::InterpolateDecoration>()) {
-            auto mod = interpolation_to_modifiers(interpolate->type(),
-                                                  interpolate->sampling());
+            auto mod = interpolation_to_modifiers(interpolate->type,
+                                                  interpolate->sampling);
             if (mod.empty()) {
               diagnostics_.add_error(diag::System::Writer,
                                      "unsupported interpolation");
@@ -2512,10 +2506,10 @@
 
 bool GeneratorImpl::EmitUnaryOp(std::ostream& out,
                                 ast::UnaryOpExpression* expr) {
-  switch (expr->op()) {
+  switch (expr->op) {
     case ast::UnaryOp::kIndirection:
     case ast::UnaryOp::kAddressOf:
-      return EmitExpression(out, expr->expr());
+      return EmitExpression(out, expr->expr);
     case ast::UnaryOp::kComplement:
       out << "~";
       break;
@@ -2528,7 +2522,7 @@
   }
   out << "(";
 
-  if (!EmitExpression(out, expr->expr())) {
+  if (!EmitExpression(out, expr->expr)) {
     return false;
   }
 
@@ -2542,7 +2536,7 @@
   auto* type = sem->Type()->UnwrapRef();
 
   // TODO(dsinclair): Handle variable decorations
-  if (!var->decorations().empty()) {
+  if (!var->decorations.empty()) {
     diagnostics_.add_error(diag::System::Writer,
                            "Variable decorations are not handled yet");
     return false;
@@ -2551,14 +2545,14 @@
   auto out = line();
   // TODO(senorblanco): handle const
   if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(),
-                       builder_.Symbols().NameFor(var->symbol()))) {
+                       builder_.Symbols().NameFor(var->symbol))) {
     return false;
   }
 
   out << " = ";
 
-  if (var->constructor()) {
-    if (!EmitExpression(out, var->constructor())) {
+  if (var->constructor) {
+    if (!EmitExpression(out, var->constructor)) {
       return false;
     }
   } else {
@@ -2572,14 +2566,14 @@
 }
 
 bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
-  for (auto* d : var->decorations()) {
+  for (auto* d : var->decorations) {
     if (!d->Is<ast::OverrideDecoration>()) {
       diagnostics_.add_error(diag::System::Writer,
                              "Decorated const values not valid");
       return false;
     }
   }
-  if (!var->is_const()) {
+  if (!var->is_const) {
     diagnostics_.add_error(diag::System::Writer, "Expected a const value");
     return false;
   }
@@ -2593,10 +2587,10 @@
 
     line() << "#ifndef " << kSpecConstantPrefix << const_id;
 
-    if (var->constructor() != nullptr) {
+    if (var->constructor != nullptr) {
       auto out = line();
       out << "#define " << kSpecConstantPrefix << const_id << " ";
-      if (!EmitExpression(out, var->constructor())) {
+      if (!EmitExpression(out, var->constructor)) {
         return false;
       }
     } else {
@@ -2607,7 +2601,7 @@
       auto out = line();
       out << "const ";
       if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(),
-                           builder_.Symbols().NameFor(var->symbol()))) {
+                           builder_.Symbols().NameFor(var->symbol))) {
         return false;
       }
       out << " = " << kSpecConstantPrefix << const_id << ";";
@@ -2616,11 +2610,11 @@
     auto out = line();
     out << "const ";
     if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(),
-                         builder_.Symbols().NameFor(var->symbol()))) {
+                         builder_.Symbols().NameFor(var->symbol))) {
       return false;
     }
     out << " = ";
-    if (!EmitExpression(out, var->constructor())) {
+    if (!EmitExpression(out, var->constructor)) {
       return false;
     }
     out << ";";
@@ -2690,7 +2684,7 @@
   {
     ScopedParen sp(out);
     bool first = true;
-    for (auto* arg : call->args()) {
+    for (auto* arg : call->args) {
       if (!first) {
         out << ", ";
       }
diff --git a/src/writer/glsl/generator_impl_case_test.cc b/src/writer/glsl/generator_impl_case_test.cc
index 10d1c51..e12a496 100644
--- a/src/writer/glsl/generator_impl_case_test.cc
+++ b/src/writer/glsl/generator_impl_case_test.cc
@@ -31,7 +31,7 @@
 
   gen.increment_indent();
 
-  ASSERT_TRUE(gen.EmitCase(s->body()[0])) << gen.error();
+  ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.error();
   EXPECT_EQ(gen.result(), R"(  case 5: {
     break;
   }
@@ -46,7 +46,7 @@
 
   gen.increment_indent();
 
-  ASSERT_TRUE(gen.EmitCase(s->body()[0])) << gen.error();
+  ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.error();
   EXPECT_EQ(gen.result(), R"(  case 5: {
     break;
   }
@@ -63,7 +63,7 @@
 
   gen.increment_indent();
 
-  ASSERT_TRUE(gen.EmitCase(s->body()[0])) << gen.error();
+  ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.error();
   EXPECT_EQ(gen.result(), R"(  case 5: {
     /* fallthrough */
   }
@@ -80,7 +80,7 @@
 
   gen.increment_indent();
 
-  ASSERT_TRUE(gen.EmitCase(s->body()[0])) << gen.error();
+  ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.error();
   EXPECT_EQ(gen.result(), R"(  case 5:
   case 6: {
     break;
@@ -96,7 +96,7 @@
 
   gen.increment_indent();
 
-  ASSERT_TRUE(gen.EmitCase(s->body()[0])) << gen.error();
+  ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.error();
   EXPECT_EQ(gen.result(), R"(  default: {
     break;
   }
diff --git a/src/writer/glsl/generator_impl_intrinsic_texture_test.cc b/src/writer/glsl/generator_impl_intrinsic_texture_test.cc
index 16075d8..e053753 100644
--- a/src/writer/glsl/generator_impl_intrinsic_texture_test.cc
+++ b/src/writer/glsl/generator_impl_intrinsic_texture_test.cc
@@ -236,8 +236,8 @@
 TEST_P(GlslGeneratorIntrinsicTextureTest, Call) {
   auto param = GetParam();
 
-  param.buildTextureVariable(this);
-  param.buildSamplerVariable(this);
+  param.BuildTextureVariable(this);
+  param.BuildSamplerVariable(this);
 
   auto* call = Call(param.function, param.args(this));
   auto* stmt = ast::intrinsic::test::ReturnsVoid(param.overload)
diff --git a/src/writer/hlsl/generator.cc b/src/writer/hlsl/generator.cc
index 2f9a58a..ce172f9 100644
--- a/src/writer/hlsl/generator.cc
+++ b/src/writer/hlsl/generator.cc
@@ -45,8 +45,8 @@
   // Collect the list of entry points in the sanitized program.
   for (auto* func : sanitized_result.program.AST().Functions()) {
     if (func->IsEntryPoint()) {
-      auto name = sanitized_result.program.Symbols().NameFor(func->symbol());
-      result.entry_points.push_back({name, func->pipeline_stage()});
+      auto name = sanitized_result.program.Symbols().NameFor(func->symbol);
+      result.entry_points.push_back({name, func->PipelineStage()});
     }
   }
 
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index 90eeaa0..b690e89 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -99,16 +99,16 @@
 // Helper for writing " : register(RX, spaceY)", where R is the register, X is
 // the binding point binding value, and Y is the binding point group value.
 struct RegisterAndSpace {
-  RegisterAndSpace(char r, ast::Variable::BindingPoint bp)
+  RegisterAndSpace(char r, ast::VariableBindingPoint bp)
       : reg(r), binding_point(bp) {}
 
   char const reg;
-  ast::Variable::BindingPoint const binding_point;
+  ast::VariableBindingPoint const binding_point;
 };
 
 std::ostream& operator<<(std::ostream& s, const RegisterAndSpace& rs) {
-  s << " : register(" << rs.reg << rs.binding_point.binding->value()
-    << ", space" << rs.binding_point.group->value() << ")";
+  s << " : register(" << rs.reg << rs.binding_point.binding->value << ", space"
+    << rs.binding_point.group->value << ")";
   return s;
 }
 
@@ -286,19 +286,19 @@
     return false;
   }
 
-  auto* ast_access_expr = stmt->lhs()->As<ast::ArrayAccessorExpression>();
+  auto* ast_access_expr = stmt->lhs->As<ast::ArrayAccessorExpression>();
 
   auto out = line();
   out << name << "(";
-  if (!EmitExpression(out, ast_access_expr->array())) {
+  if (!EmitExpression(out, ast_access_expr->array)) {
     return false;
   }
   out << ", ";
-  if (!EmitExpression(out, ast_access_expr->idx_expr())) {
+  if (!EmitExpression(out, ast_access_expr->index)) {
     return false;
   }
   out << ", ";
-  if (!EmitExpression(out, stmt->rhs())) {
+  if (!EmitExpression(out, stmt->rhs)) {
     return false;
   }
   out << ");";
@@ -308,12 +308,12 @@
 
 bool GeneratorImpl::EmitArrayAccessor(std::ostream& out,
                                       ast::ArrayAccessorExpression* expr) {
-  if (!EmitExpression(out, expr->array())) {
+  if (!EmitExpression(out, expr->array)) {
     return false;
   }
   out << "[";
 
-  if (!EmitExpression(out, expr->idx_expr())) {
+  if (!EmitExpression(out, expr->index)) {
     return false;
   }
   out << "]";
@@ -340,7 +340,7 @@
     return false;
   }
   out << "(";
-  if (!EmitExpression(out, expr->expr())) {
+  if (!EmitExpression(out, expr->expr)) {
     return false;
   }
   out << ")";
@@ -348,9 +348,9 @@
 }
 
 bool GeneratorImpl::EmitAssign(ast::AssignmentStatement* stmt) {
-  if (auto* idx = stmt->lhs()->As<ast::ArrayAccessorExpression>()) {
-    if (auto* vec = TypeOf(idx->array())->UnwrapRef()->As<sem::Vector>()) {
-      auto* rhs_sem = builder_.Sem().Get(idx->idx_expr());
+  if (auto* idx = stmt->lhs->As<ast::ArrayAccessorExpression>()) {
+    if (auto* vec = TypeOf(idx->array)->UnwrapRef()->As<sem::Vector>()) {
+      auto* rhs_sem = builder_.Sem().Get(idx->index);
       if (!rhs_sem->ConstantValue().IsValid()) {
         return EmitDynamicVectorAssignment(stmt, vec);
       }
@@ -358,11 +358,11 @@
   }
 
   auto out = line();
-  if (!EmitExpression(out, stmt->lhs())) {
+  if (!EmitExpression(out, stmt->lhs)) {
     return false;
   }
   out << " = ";
-  if (!EmitExpression(out, stmt->rhs())) {
+  if (!EmitExpression(out, stmt->rhs)) {
     return false;
   }
   out << ";";
@@ -370,20 +370,20 @@
 }
 
 bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) {
-  if (expr->op() == ast::BinaryOp::kLogicalAnd ||
-      expr->op() == ast::BinaryOp::kLogicalOr) {
+  if (expr->op == ast::BinaryOp::kLogicalAnd ||
+      expr->op == ast::BinaryOp::kLogicalOr) {
     auto name = UniqueIdentifier(kTempNamePrefix);
 
     {
       auto pre = line();
       pre << "bool " << name << " = ";
-      if (!EmitExpression(pre, expr->lhs())) {
+      if (!EmitExpression(pre, expr->lhs)) {
         return false;
       }
       pre << ";";
     }
 
-    if (expr->op() == ast::BinaryOp::kLogicalOr) {
+    if (expr->op == ast::BinaryOp::kLogicalOr) {
       line() << "if (!" << name << ") {";
     } else {
       line() << "if (" << name << ") {";
@@ -393,7 +393,7 @@
       ScopedIndent si(this);
       auto pre = line();
       pre << name << " = ";
-      if (!EmitExpression(pre, expr->rhs())) {
+      if (!EmitExpression(pre, expr->rhs)) {
         return false;
       }
       pre << ";";
@@ -405,21 +405,21 @@
     return true;
   }
 
-  auto* lhs_type = TypeOf(expr->lhs())->UnwrapRef();
-  auto* rhs_type = TypeOf(expr->rhs())->UnwrapRef();
+  auto* lhs_type = TypeOf(expr->lhs)->UnwrapRef();
+  auto* rhs_type = TypeOf(expr->rhs)->UnwrapRef();
   // Multiplying by a matrix requires the use of `mul` in order to get the
   // type of multiply we desire.
-  if (expr->op() == ast::BinaryOp::kMultiply &&
+  if (expr->op == ast::BinaryOp::kMultiply &&
       ((lhs_type->Is<sem::Vector>() && rhs_type->Is<sem::Matrix>()) ||
        (lhs_type->Is<sem::Matrix>() && rhs_type->Is<sem::Vector>()) ||
        (lhs_type->Is<sem::Matrix>() && rhs_type->Is<sem::Matrix>()))) {
     // Matrices are transposed, so swap LHS and RHS.
     out << "mul(";
-    if (!EmitExpression(out, expr->rhs())) {
+    if (!EmitExpression(out, expr->rhs)) {
       return false;
     }
     out << ", ";
-    if (!EmitExpression(out, expr->lhs())) {
+    if (!EmitExpression(out, expr->lhs)) {
       return false;
     }
     out << ")";
@@ -430,12 +430,12 @@
   out << "(";
   TINT_DEFER(out << ")");
 
-  if (!EmitExpression(out, expr->lhs())) {
+  if (!EmitExpression(out, expr->lhs)) {
     return false;
   }
   out << " ";
 
-  switch (expr->op()) {
+  switch (expr->op) {
     case ast::BinaryOp::kAnd:
       out << "&";
       break;
@@ -492,7 +492,7 @@
     case ast::BinaryOp::kDivide:
       out << "/";
 
-      if (auto val = program_->Sem().Get(expr->rhs())->ConstantValue()) {
+      if (auto val = program_->Sem().Get(expr->rhs)->ConstantValue()) {
         // Integer divide by zero is a DXC compile error, and undefined behavior
         // in WGSL. Replace the 0 with 1.
         if (val.Type()->Is<sem::I32>() && val.Elements()[0].i32 == 0) {
@@ -515,7 +515,7 @@
   }
   out << " ";
 
-  if (!EmitExpression(out, expr->rhs())) {
+  if (!EmitExpression(out, expr->rhs)) {
     return false;
   }
 
@@ -538,7 +538,7 @@
 
 bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
   line() << "{";
-  if (!EmitStatementsWithIndent(stmt->statements())) {
+  if (!EmitStatementsWithIndent(stmt->statements)) {
     return false;
   }
   line() << "}";
@@ -551,15 +551,15 @@
 }
 
 bool GeneratorImpl::EmitCall(std::ostream& out, ast::CallExpression* expr) {
-  const auto& args = expr->args();
-  auto* ident = expr->func();
+  const auto& args = expr->args;
+  auto* ident = expr->func;
   auto* call = builder_.Sem().Get(expr);
   auto* target = call->Target();
 
   if (auto* func = target->As<sem::Function>()) {
     if (ast::HasDecoration<
             transform::CalculateArrayLength::BufferSizeIntrinsic>(
-            func->Declaration()->decorations())) {
+            func->Declaration()->decorations)) {
       // Special function generated by the CalculateArrayLength transform for
       // calling X.GetDimensions(Y)
       if (!EmitExpression(out, args[0])) {
@@ -575,7 +575,7 @@
 
     if (auto* intrinsic =
             ast::GetDecoration<transform::DecomposeMemoryAccess::Intrinsic>(
-                func->Declaration()->decorations())) {
+                func->Declaration()->decorations)) {
       switch (intrinsic->storage_class) {
         case ast::StorageClass::kUniform:
           return EmitUniformBufferAccess(out, expr, intrinsic);
@@ -602,7 +602,7 @@
     } else if (intrinsic->Type() == sem::IntrinsicType::kIsNormal) {
       return EmitIsNormalCall(out, expr, intrinsic);
     } else if (intrinsic->Type() == sem::IntrinsicType::kIgnore) {
-      return EmitExpression(out, expr->args()[0]);
+      return EmitExpression(out, expr->args[0]);
     } else if (intrinsic->IsDataPacking()) {
       return EmitDataPackingCall(out, expr, intrinsic);
     } else if (intrinsic->IsDataUnpacking()) {
@@ -635,14 +635,14 @@
     return true;
   }
 
-  auto name = builder_.Symbols().NameFor(ident->symbol());
-  auto caller_sym = ident->symbol();
+  auto name = builder_.Symbols().NameFor(ident->symbol);
+  auto caller_sym = ident->symbol;
 
-  auto* func = builder_.AST().Functions().Find(ident->symbol());
+  auto* func = builder_.AST().Functions().Find(ident->symbol);
   if (func == nullptr) {
     diagnostics_.add_error(diag::System::Writer,
                            "Unable to find function: " +
-                               builder_.Symbols().NameFor(ident->symbol()));
+                               builder_.Symbols().NameFor(ident->symbol));
     return false;
   }
 
@@ -669,7 +669,7 @@
     std::ostream& out,
     ast::CallExpression* expr,
     const transform::DecomposeMemoryAccess::Intrinsic* intrinsic) {
-  const auto& args = expr->args();
+  const auto& args = expr->args;
   auto* offset_arg = builder_.Sem().Get(args[1]);
 
   uint32_t scalar_offset_value = 0;
@@ -808,7 +808,7 @@
     std::ostream& out,
     ast::CallExpression* expr,
     const transform::DecomposeMemoryAccess::Intrinsic* intrinsic) {
-  const auto& args = expr->args();
+  const auto& args = expr->args;
 
   using Op = transform::DecomposeMemoryAccess::Intrinsic::Op;
   using DataType = transform::DecomposeMemoryAccess::Intrinsic::DataType;
@@ -1057,7 +1057,7 @@
       case Op::kAtomicStore: {
         // HLSL does not have an InterlockedStore, so we emulate it with
         // InterlockedExchange and discard the returned value
-        auto* value_ty = TypeOf(expr->args()[2])->UnwrapRef();
+        auto* value_ty = TypeOf(expr->args[2])->UnwrapRef();
         auto name = UniqueIdentifier("atomicStore");
         {
           auto fn = line(&buf);
@@ -1088,7 +1088,7 @@
         return name;
       }
       case Op::kAtomicCompareExchangeWeak: {
-        auto* value_ty = TypeOf(expr->args()[2])->UnwrapRef();
+        auto* value_ty = TypeOf(expr->args[2])->UnwrapRef();
 
         auto name = UniqueIdentifier("atomicCompareExchangeWeak");
         {
@@ -1151,7 +1151,7 @@
   {
     ScopedParen sp(out);
     bool first = true;
-    for (auto* arg : expr->args()) {
+    for (auto* arg : expr->args) {
       if (!first) {
         out << ", ";
       }
@@ -1189,8 +1189,8 @@
 
     {
       ScopedParen sp(pre);
-      for (size_t i = 0; i < expr->args().size(); i++) {
-        auto* arg = expr->args()[i];
+      for (size_t i = 0; i < expr->args.size(); i++) {
+        auto* arg = expr->args[i];
         if (i > 0) {
           pre << ", ";
         }
@@ -1220,7 +1220,7 @@
       pre << "InterlockedOr";
       {
         ScopedParen sp(pre);
-        if (!EmitExpression(pre, expr->args()[0])) {
+        if (!EmitExpression(pre, expr->args[0])) {
           return false;
         }
         pre << ", 0, " << result;
@@ -1250,11 +1250,11 @@
       out << "InterlockedExchange";
       {
         ScopedParen sp(out);
-        if (!EmitExpression(out, expr->args()[0])) {
+        if (!EmitExpression(out, expr->args[0])) {
           return false;
         }
         out << ", ";
-        if (!EmitExpression(out, expr->args()[1])) {
+        if (!EmitExpression(out, expr->args[1])) {
           return false;
         }
         out << ", " << result;
@@ -1262,9 +1262,9 @@
       return true;
     }
     case sem::IntrinsicType::kAtomicCompareExchangeWeak: {
-      auto* dest = expr->args()[0];
-      auto* compare_value = expr->args()[1];
-      auto* value = expr->args()[2];
+      auto* dest = expr->args[0];
+      auto* compare_value = expr->args[1];
+      auto* value = expr->args[2];
 
       std::string compare = UniqueIdentifier("atomic_compare_value");
 
@@ -1340,9 +1340,9 @@
 
 bool GeneratorImpl::EmitSelectCall(std::ostream& out,
                                    ast::CallExpression* expr) {
-  auto* expr_false = expr->args()[0];
-  auto* expr_true = expr->args()[1];
-  auto* expr_cond = expr->args()[2];
+  auto* expr_false = expr->args[0];
+  auto* expr_true = expr->args[1];
+  auto* expr_cond = expr->args[2];
   ScopedParen paren(out);
   if (!EmitExpression(out, expr_cond)) {
     return false;
@@ -1621,7 +1621,7 @@
   using Usage = sem::ParameterUsage;
 
   auto& signature = intrinsic->Signature();
-  auto arguments = expr->args();
+  auto arguments = expr->args;
 
   // Returns the argument with the given usage
   auto arg = [&](Usage usage) {
@@ -2057,18 +2057,18 @@
 }
 
 bool GeneratorImpl::EmitCase(ast::SwitchStatement* s, size_t case_idx) {
-  auto* stmt = s->body()[case_idx];
+  auto* stmt = s->body[case_idx];
   if (stmt->IsDefault()) {
     line() << "default: {";
   } else {
-    for (auto* selector : stmt->selectors()) {
+    for (auto* selector : stmt->selectors) {
       auto out = line();
       out << "case ";
       if (!EmitLiteral(out, selector)) {
         return false;
       }
       out << ":";
-      if (selector == stmt->selectors().back()) {
+      if (selector == stmt->selectors.back()) {
         out << " {";
       }
     }
@@ -2081,23 +2081,23 @@
   });
 
   // Emit the case statement
-  if (!EmitStatements(stmt->body()->statements())) {
+  if (!EmitStatements(stmt->body->statements)) {
     return false;
   }
 
   // Inline all fallthrough case statements. FXC cannot handle fallthroughs.
-  while (tint::Is<ast::FallthroughStatement>(stmt->body()->last())) {
+  while (tint::Is<ast::FallthroughStatement>(stmt->body->Last())) {
     case_idx++;
-    stmt = s->body()[case_idx];
+    stmt = s->body[case_idx];
     // Generate each fallthrough case statement in a new block. This is done to
     // prevent symbol collision of variables declared in these cases statements.
-    if (!EmitBlock(stmt->body())) {
+    if (!EmitBlock(stmt->body)) {
       return false;
     }
   }
 
   if (!tint::IsAnyOf<ast::BreakStatement, ast::FallthroughStatement>(
-          stmt->body()->last())) {
+          stmt->body->Last())) {
     line() << "break;";
   }
 
@@ -2115,7 +2115,7 @@
 bool GeneratorImpl::EmitScalarConstructor(
     std::ostream& out,
     ast::ScalarConstructorExpression* expr) {
-  return EmitLiteral(out, expr->literal());
+  return EmitLiteral(out, expr->literal);
 }
 
 bool GeneratorImpl::EmitTypeConstructor(std::ostream& out,
@@ -2124,7 +2124,7 @@
 
   // If the type constructor is empty then we need to construct with the zero
   // value for all components.
-  if (expr->values().empty()) {
+  if (expr->values.empty()) {
     return EmitZeroValue(out, type);
   }
 
@@ -2133,8 +2133,8 @@
   // For single-value vector initializers, swizzle the scalar to the right
   // vector dimension using .x
   const bool is_single_value_vector_init =
-      type->is_scalar_vector() && expr->values().size() == 1 &&
-      TypeOf(expr->values()[0])->UnwrapRef()->is_scalar();
+      type->is_scalar_vector() && expr->values.size() == 1 &&
+      TypeOf(expr->values[0])->UnwrapRef()->is_scalar();
 
   auto it = structure_builders_.find(As<sem::Struct>(type));
   if (it != structure_builders_.end()) {
@@ -2155,7 +2155,7 @@
   }
 
   bool first = true;
-  for (auto* e : expr->values()) {
+  for (auto* e : expr->values) {
     if (!first) {
       out << ", ";
     }
@@ -2223,7 +2223,7 @@
 
 bool GeneratorImpl::EmitIdentifier(std::ostream& out,
                                    ast::IdentifierExpression* expr) {
-  out << builder_.Symbols().NameFor(expr->symbol());
+  out << builder_.Symbols().NameFor(expr->symbol);
   return true;
 }
 
@@ -2231,25 +2231,25 @@
   {
     auto out = line();
     out << "if (";
-    if (!EmitExpression(out, stmt->condition())) {
+    if (!EmitExpression(out, stmt->condition)) {
       return false;
     }
     out << ") {";
   }
 
-  if (!EmitStatementsWithIndent(stmt->body()->statements())) {
+  if (!EmitStatementsWithIndent(stmt->body->statements)) {
     return false;
   }
 
-  for (auto* e : stmt->else_statements()) {
-    if (e->HasCondition()) {
+  for (auto* e : stmt->else_statements) {
+    if (e->condition) {
       line() << "} else {";
       increment_indent();
 
       {
         auto out = line();
         out << "if (";
-        if (!EmitExpression(out, e->condition())) {
+        if (!EmitExpression(out, e->condition)) {
           return false;
         }
         out << ") {";
@@ -2258,15 +2258,15 @@
       line() << "} else {";
     }
 
-    if (!EmitStatementsWithIndent(e->body()->statements())) {
+    if (!EmitStatementsWithIndent(e->body->statements)) {
       return false;
     }
   }
 
   line() << "}";
 
-  for (auto* e : stmt->else_statements()) {
-    if (e->HasCondition()) {
+  for (auto* e : stmt->else_statements) {
+    if (e->condition) {
       decrement_indent();
       line() << "}";
     }
@@ -2277,14 +2277,14 @@
 bool GeneratorImpl::EmitFunction(ast::Function* func) {
   auto* sem = builder_.Sem().Get(func);
 
-  if (ast::HasDecoration<ast::InternalDecoration>(func->decorations())) {
+  if (ast::HasDecoration<ast::InternalDecoration>(func->decorations)) {
     // An internal function. Do not emit.
     return true;
   }
 
   {
     auto out = line();
-    auto name = builder_.Symbols().NameFor(func->symbol());
+    auto name = builder_.Symbols().NameFor(func->symbol);
     // If the function returns an array, then we need to declare a typedef for
     // this.
     if (sem->ReturnType()->Is<sem::Array>()) {
@@ -2333,14 +2333,14 @@
       // storage buffers and a uint4[N] for uniform buffers.
       if (!EmitTypeAndName(
               out, type, v->StorageClass(), v->Access(),
-              builder_.Symbols().NameFor(v->Declaration()->symbol()))) {
+              builder_.Symbols().NameFor(v->Declaration()->symbol))) {
         return false;
       }
     }
     out << ") {";
   }
 
-  if (!EmitStatementsWithIndent(func->body()->statements())) {
+  if (!EmitStatementsWithIndent(func->body->statements)) {
     return false;
   }
 
@@ -2350,7 +2350,7 @@
 }
 
 bool GeneratorImpl::EmitGlobalVariable(ast::Variable* global) {
-  if (global->is_const()) {
+  if (global->is_const) {
     return EmitProgramConstVariable(global);
   }
 
@@ -2377,7 +2377,7 @@
 
 bool GeneratorImpl::EmitUniformVariable(const sem::Variable* var) {
   auto* decl = var->Declaration();
-  auto binding_point = decl->binding_point();
+  auto binding_point = decl->BindingPoint();
   auto* type = var->Type()->UnwrapRef();
 
   auto* str = type->As<sem::Struct>();
@@ -2387,7 +2387,7 @@
         << "variables with uniform storage must be structure";
   }
 
-  auto name = builder_.Symbols().NameFor(decl->symbol());
+  auto name = builder_.Symbols().NameFor(decl->symbol);
   line() << "cbuffer cbuffer_" << name << RegisterAndSpace('b', binding_point)
          << " {";
 
@@ -2411,12 +2411,12 @@
   auto* type = var->Type()->UnwrapRef();
   auto out = line();
   if (!EmitTypeAndName(out, type, ast::StorageClass::kStorage, var->Access(),
-                       builder_.Symbols().NameFor(decl->symbol()))) {
+                       builder_.Symbols().NameFor(decl->symbol))) {
     return false;
   }
 
   out << RegisterAndSpace(var->Access() == ast::Access::kRead ? 't' : 'u',
-                          decl->binding_point())
+                          decl->BindingPoint())
       << ";";
 
   return true;
@@ -2427,7 +2427,7 @@
   auto* unwrapped_type = var->Type()->UnwrapRef();
   auto out = line();
 
-  auto name = builder_.Symbols().NameFor(decl->symbol());
+  auto name = builder_.Symbols().NameFor(decl->symbol);
   auto* type = var->Type()->UnwrapRef();
   if (!EmitTypeAndName(out, type, var->StorageClass(), var->Access(), name)) {
     return false;
@@ -2445,9 +2445,9 @@
   }
 
   if (register_space) {
-    auto bp = decl->binding_point();
-    out << " : register(" << register_space << bp.binding->value() << ", space"
-        << bp.group->value() << ")";
+    auto bp = decl->BindingPoint();
+    out << " : register(" << register_space << bp.binding->value << ", space"
+        << bp.group->value << ")";
   }
 
   out << ";";
@@ -2460,14 +2460,14 @@
 
   out << "static ";
 
-  auto name = builder_.Symbols().NameFor(decl->symbol());
+  auto name = builder_.Symbols().NameFor(decl->symbol);
   auto* type = var->Type()->UnwrapRef();
   if (!EmitTypeAndName(out, type, var->StorageClass(), var->Access(), name)) {
     return false;
   }
 
   out << " = ";
-  if (auto* constructor = decl->constructor()) {
+  if (auto* constructor = decl->constructor) {
     if (!EmitExpression(out, constructor)) {
       return false;
     }
@@ -2487,13 +2487,13 @@
 
   out << "groupshared ";
 
-  auto name = builder_.Symbols().NameFor(decl->symbol());
+  auto name = builder_.Symbols().NameFor(decl->symbol);
   auto* type = var->Type()->UnwrapRef();
   if (!EmitTypeAndName(out, type, var->StorageClass(), var->Access(), name)) {
     return false;
   }
 
-  if (auto* constructor = decl->constructor()) {
+  if (auto* constructor = decl->constructor) {
     out << " = ";
     if (!EmitExpression(out, constructor)) {
       return false;
@@ -2568,7 +2568,7 @@
 
   {
     auto out = line();
-    if (func->pipeline_stage() == ast::PipelineStage::kCompute) {
+    if (func->PipelineStage() == ast::PipelineStage::kCompute) {
       // Emit the workgroup_size attribute.
       auto wgsize = func_sem->workgroup_size();
       out << "[numthreads(";
@@ -2592,14 +2592,14 @@
       out << ")]" << std::endl;
     }
 
-    out << func->return_type()->FriendlyName(builder_.Symbols());
+    out << func->return_type->FriendlyName(builder_.Symbols());
 
-    out << " " << builder_.Symbols().NameFor(func->symbol()) << "(";
+    out << " " << builder_.Symbols().NameFor(func->symbol) << "(";
 
     bool first = true;
 
     // Emit entry point parameters.
-    for (auto* var : func->params()) {
+    for (auto* var : func->params) {
       auto* sem = builder_.Sem().Get(var);
       auto* type = sem->Type();
       if (!type->Is<sem::Struct>()) {
@@ -2615,7 +2615,7 @@
       first = false;
 
       if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(),
-                           builder_.Symbols().NameFor(var->symbol()))) {
+                           builder_.Symbols().NameFor(var->symbol))) {
         return false;
       }
     }
@@ -2626,11 +2626,11 @@
   {
     ScopedIndent si(this);
 
-    if (!EmitStatements(func->body()->statements())) {
+    if (!EmitStatements(func->body->statements)) {
       return false;
     }
 
-    if (!Is<ast::ReturnStatement>(func->get_last_statement())) {
+    if (!Is<ast::ReturnStatement>(func->body->Last())) {
       ast::ReturnStatement ret(ProgramID(), Source{});
       if (!EmitStatement(&ret)) {
         return false;
@@ -2645,20 +2645,19 @@
 
 bool GeneratorImpl::EmitLiteral(std::ostream& out, ast::Literal* lit) {
   if (auto* l = lit->As<ast::BoolLiteral>()) {
-    out << (l->IsTrue() ? "true" : "false");
+    out << (l->value ? "true" : "false");
   } else if (auto* fl = lit->As<ast::FloatLiteral>()) {
-    if (std::isinf(fl->value())) {
-      out << (fl->value() >= 0 ? "asfloat(0x7f800000u)"
-                               : "asfloat(0xff800000u)");
-    } else if (std::isnan(fl->value())) {
+    if (std::isinf(fl->value)) {
+      out << (fl->value >= 0 ? "asfloat(0x7f800000u)" : "asfloat(0xff800000u)");
+    } else if (std::isnan(fl->value)) {
       out << "asfloat(0x7fc00000u)";
     } else {
-      out << FloatToString(fl->value()) << "f";
+      out << FloatToString(fl->value) << "f";
     }
   } else if (auto* sl = lit->As<ast::SintLiteral>()) {
-    out << sl->value();
+    out << sl->value;
   } else if (auto* ul = lit->As<ast::UintLiteral>()) {
-    out << ul->value() << "u";
+    out << ul->value << "u";
   } else {
     diagnostics_.add_error(diag::System::Writer, "unknown literal type");
     return false;
@@ -2721,8 +2720,8 @@
 
 bool GeneratorImpl::EmitLoop(ast::LoopStatement* stmt) {
   auto emit_continuing = [this, stmt]() {
-    if (stmt->has_continuing()) {
-      if (!EmitBlock(stmt->continuing())) {
+    if (stmt->continuing && !stmt->continuing->Empty()) {
+      if (!EmitBlock(stmt->continuing)) {
         return false;
       }
     }
@@ -2733,7 +2732,7 @@
   line() << "while (true) {";
   {
     ScopedIndent si(this);
-    if (!EmitStatements(stmt->body()->statements())) {
+    if (!EmitStatements(stmt->body->statements)) {
       return false;
     }
     if (!emit_continuing()) {
@@ -2756,7 +2755,7 @@
   });
 
   TextBuffer init_buf;
-  if (auto* init = stmt->initializer()) {
+  if (auto* init = stmt->initializer) {
     TINT_SCOPED_ASSIGNMENT(current_buffer_, &init_buf);
     if (!EmitStatement(init)) {
       return false;
@@ -2765,7 +2764,7 @@
 
   TextBuffer cond_pre;
   std::stringstream cond_buf;
-  if (auto* cond = stmt->condition()) {
+  if (auto* cond = stmt->condition) {
     TINT_SCOPED_ASSIGNMENT(current_buffer_, &cond_pre);
     if (!EmitExpression(cond_buf, cond)) {
       return false;
@@ -2773,7 +2772,7 @@
   }
 
   TextBuffer cont_buf;
-  if (auto* cont = stmt->continuing()) {
+  if (auto* cont = stmt->continuing) {
     TINT_SCOPED_ASSIGNMENT(current_buffer_, &cont_buf);
     if (!EmitStatement(cont)) {
       return false;
@@ -2788,7 +2787,7 @@
   // If the for-loop has multi-statement initializer, or is going to be emitted
   // as a `while(true)` loop, then declare the initializer statement(s) before
   // the loop.
-  if (init_buf.lines.size() > 1 || (stmt->initializer() && emit_as_loop)) {
+  if (init_buf.lines.size() > 1 || (stmt->initializer && emit_as_loop)) {
     current_buffer_->Append(init_buf);
     init_buf.lines.clear();  // Don't emit the initializer again in the 'for'
   }
@@ -2807,12 +2806,12 @@
       line() << "}";
     });
 
-    if (stmt->condition()) {
+    if (stmt->condition) {
       current_buffer_->Append(cond_pre);
       line() << "if (!(" << cond_buf.str() << ")) { break; }";
     }
 
-    if (!EmitStatements(stmt->body()->statements())) {
+    if (!EmitStatements(stmt->body->statements)) {
       return false;
     }
 
@@ -2844,7 +2843,7 @@
     {
       auto emit_continuing = [] { return true; };
       TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
-      if (!EmitStatementsWithIndent(stmt->body()->statements())) {
+      if (!EmitStatementsWithIndent(stmt->body->statements)) {
         return false;
       }
     }
@@ -2856,15 +2855,15 @@
 
 bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
                                        ast::MemberAccessorExpression* expr) {
-  if (!EmitExpression(out, expr->structure())) {
+  if (!EmitExpression(out, expr->structure)) {
     return false;
   }
   out << ".";
 
   // Swizzles output the name directly
   if (builder_.Sem().Get(expr)->Is<sem::Swizzle>()) {
-    out << builder_.Symbols().NameFor(expr->member()->symbol());
-  } else if (!EmitExpression(out, expr->member())) {
+    out << builder_.Symbols().NameFor(expr->member->symbol);
+  } else if (!EmitExpression(out, expr->member)) {
     return false;
   }
 
@@ -2872,10 +2871,10 @@
 }
 
 bool GeneratorImpl::EmitReturn(ast::ReturnStatement* stmt) {
-  if (stmt->has_value()) {
+  if (stmt->value) {
     auto out = line();
     out << "return ";
-    if (!EmitExpression(out, stmt->value())) {
+    if (!EmitExpression(out, stmt->value)) {
       return false;
     }
     out << ";";
@@ -2897,10 +2896,10 @@
   }
   if (auto* c = stmt->As<ast::CallStatement>()) {
     auto out = line();
-    if (!TypeOf(c->expr())->Is<sem::Void>()) {
+    if (!TypeOf(c->expr)->Is<sem::Void>()) {
       out << "(void) ";
     }
-    if (!EmitCall(out, c->expr())) {
+    if (!EmitCall(out, c->expr)) {
       return false;
     }
     out << ";";
@@ -2932,7 +2931,7 @@
     return EmitSwitch(s);
   }
   if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
-    return EmitVariable(v->variable());
+    return EmitVariable(v->variable);
   }
 
   diagnostics_.add_error(
@@ -2945,7 +2944,7 @@
   {  // switch(expr) {
     auto out = line();
     out << "switch(";
-    if (!EmitExpression(out, stmt->condition())) {
+    if (!EmitExpression(out, stmt->condition)) {
       return false;
     }
     out << ") {";
@@ -2953,7 +2952,7 @@
 
   {
     ScopedIndent si(this);
-    for (size_t i = 0; i < stmt->body().size(); i++) {
+    for (size_t i = 0; i < stmt->body.size(); i++) {
       if (!EmitCase(stmt, i)) {
         return false;
       }
@@ -3180,7 +3179,7 @@
       std::string pre, post;
 
       if (auto* decl = mem->Declaration()) {
-        for (auto* deco : decl->decorations()) {
+        for (auto* deco : decl->decorations) {
           if (auto* location = deco->As<ast::LocationDecoration>()) {
             auto& pipeline_stage_uses = str->PipelineStageUses();
             if (pipeline_stage_uses.size() != 1) {
@@ -3190,22 +3189,22 @@
 
             if (pipeline_stage_uses.count(
                     sem::PipelineStageUsage::kVertexInput)) {
-              post += " : TEXCOORD" + std::to_string(location->value());
+              post += " : TEXCOORD" + std::to_string(location->value);
             } else if (pipeline_stage_uses.count(
                            sem::PipelineStageUsage::kVertexOutput)) {
-              post += " : TEXCOORD" + std::to_string(location->value());
+              post += " : TEXCOORD" + std::to_string(location->value);
             } else if (pipeline_stage_uses.count(
                            sem::PipelineStageUsage::kFragmentInput)) {
-              post += " : TEXCOORD" + std::to_string(location->value());
+              post += " : TEXCOORD" + std::to_string(location->value);
             } else if (pipeline_stage_uses.count(
                            sem::PipelineStageUsage::kFragmentOutput)) {
-              post += " : SV_Target" + std::to_string(location->value());
+              post += " : SV_Target" + std::to_string(location->value);
             } else {
               TINT_ICE(Writer, diagnostics_)
                   << "invalid use of location decoration";
             }
           } else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
-            auto attr = builtin_to_attribute(builtin->value());
+            auto attr = builtin_to_attribute(builtin->builtin);
             if (attr.empty()) {
               diagnostics_.add_error(diag::System::Writer,
                                      "unsupported builtin");
@@ -3214,8 +3213,8 @@
             post += " : " + attr;
           } else if (auto* interpolate =
                          deco->As<ast::InterpolateDecoration>()) {
-            auto mod = interpolation_to_modifiers(interpolate->type(),
-                                                  interpolate->sampling());
+            auto mod = interpolation_to_modifiers(interpolate->type,
+                                                  interpolate->sampling);
             if (mod.empty()) {
               diagnostics_.add_error(diag::System::Writer,
                                      "unsupported interpolation");
@@ -3232,7 +3231,7 @@
                                     ast::StructMemberOffsetDecoration,
                                     ast::StructMemberSizeDecoration>()) {
             TINT_ICE(Writer, diagnostics_)
-                << "unhandled struct member attribute: " << deco->name();
+                << "unhandled struct member attribute: " << deco->Name();
             return false;
           }
         }
@@ -3254,10 +3253,10 @@
 
 bool GeneratorImpl::EmitUnaryOp(std::ostream& out,
                                 ast::UnaryOpExpression* expr) {
-  switch (expr->op()) {
+  switch (expr->op) {
     case ast::UnaryOp::kIndirection:
     case ast::UnaryOp::kAddressOf:
-      return EmitExpression(out, expr->expr());
+      return EmitExpression(out, expr->expr);
     case ast::UnaryOp::kComplement:
       out << "~";
       break;
@@ -3270,7 +3269,7 @@
   }
   out << "(";
 
-  if (!EmitExpression(out, expr->expr())) {
+  if (!EmitExpression(out, expr->expr)) {
     return false;
   }
 
@@ -3284,25 +3283,25 @@
   auto* type = sem->Type()->UnwrapRef();
 
   // TODO(dsinclair): Handle variable decorations
-  if (!var->decorations().empty()) {
+  if (!var->decorations.empty()) {
     diagnostics_.add_error(diag::System::Writer,
                            "Variable decorations are not handled yet");
     return false;
   }
 
   auto out = line();
-  if (var->is_const()) {
+  if (var->is_const) {
     out << "const ";
   }
   if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(),
-                       builder_.Symbols().NameFor(var->symbol()))) {
+                       builder_.Symbols().NameFor(var->symbol))) {
     return false;
   }
 
   out << " = ";
 
-  if (var->constructor()) {
-    if (!EmitExpression(out, var->constructor())) {
+  if (var->constructor) {
+    if (!EmitExpression(out, var->constructor)) {
       return false;
     }
   } else {
@@ -3316,14 +3315,14 @@
 }
 
 bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
-  for (auto* d : var->decorations()) {
+  for (auto* d : var->decorations) {
     if (!d->Is<ast::OverrideDecoration>()) {
       diagnostics_.add_error(diag::System::Writer,
                              "Decorated const values not valid");
       return false;
     }
   }
-  if (!var->is_const()) {
+  if (!var->is_const) {
     diagnostics_.add_error(diag::System::Writer, "Expected a const value");
     return false;
   }
@@ -3337,10 +3336,10 @@
 
     line() << "#ifndef " << kSpecConstantPrefix << const_id;
 
-    if (var->constructor() != nullptr) {
+    if (var->constructor != nullptr) {
       auto out = line();
       out << "#define " << kSpecConstantPrefix << const_id << " ";
-      if (!EmitExpression(out, var->constructor())) {
+      if (!EmitExpression(out, var->constructor)) {
         return false;
       }
     } else {
@@ -3351,7 +3350,7 @@
       auto out = line();
       out << "static const ";
       if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(),
-                           builder_.Symbols().NameFor(var->symbol()))) {
+                           builder_.Symbols().NameFor(var->symbol))) {
         return false;
       }
       out << " = " << kSpecConstantPrefix << const_id << ";";
@@ -3360,11 +3359,11 @@
     auto out = line();
     out << "static const ";
     if (!EmitTypeAndName(out, type, sem->StorageClass(), sem->Access(),
-                         builder_.Symbols().NameFor(var->symbol()))) {
+                         builder_.Symbols().NameFor(var->symbol))) {
       return false;
     }
     out << " = ";
-    if (!EmitExpression(out, var->constructor())) {
+    if (!EmitExpression(out, var->constructor)) {
       return false;
     }
     out << ";";
@@ -3434,7 +3433,7 @@
   {
     ScopedParen sp(out);
     bool first = true;
-    for (auto* arg : call->args()) {
+    for (auto* arg : call->args) {
       if (!first) {
         out << ", ";
       }
diff --git a/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc b/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc
index b19864d..ff9cf34 100644
--- a/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc
+++ b/src/writer/hlsl/generator_impl_intrinsic_texture_test.cc
@@ -331,8 +331,8 @@
 TEST_P(HlslGeneratorIntrinsicTextureTest, Call) {
   auto param = GetParam();
 
-  param.buildTextureVariable(this);
-  param.buildSamplerVariable(this);
+  param.BuildTextureVariable(this);
+  param.BuildSamplerVariable(this);
 
   auto* call = Call(param.function, param.args(this));
   auto* stmt = ast::intrinsic::test::ReturnsVoid(param.overload)
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index 3ecf89b..510b649 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -77,12 +77,7 @@
 namespace {
 
 bool last_is_break_or_fallthrough(const ast::BlockStatement* stmts) {
-  if (stmts->empty()) {
-    return false;
-  }
-
-  return stmts->last()->Is<ast::BreakStatement>() ||
-         stmts->last()->Is<ast::FallthroughStatement>();
+  return IsAnyOf<ast::BreakStatement, ast::FallthroughStatement>(stmts->Last());
 }
 
 class ScopedBitCast {
@@ -192,7 +187,7 @@
   }
 
   for (auto* var : program_->AST().GlobalVariables()) {
-    if (var->is_const()) {
+    if (var->is_const) {
       if (!EmitProgramConstVariable(var)) {
         return false;
       }
@@ -250,7 +245,7 @@
 bool GeneratorImpl::EmitArrayAccessor(std::ostream& out,
                                       ast::ArrayAccessorExpression* expr) {
   bool paren_lhs =
-      !expr->array()
+      !expr->array
            ->IsAnyOf<ast::ArrayAccessorExpression, ast::CallExpression,
                      ast::IdentifierExpression, ast::MemberAccessorExpression,
                      ast::TypeConstructorExpression>();
@@ -258,7 +253,7 @@
   if (paren_lhs) {
     out << "(";
   }
-  if (!EmitExpression(out, expr->array())) {
+  if (!EmitExpression(out, expr->array)) {
     return false;
   }
   if (paren_lhs) {
@@ -267,7 +262,7 @@
 
   out << "[";
 
-  if (!EmitExpression(out, expr->idx_expr())) {
+  if (!EmitExpression(out, expr->index)) {
     return false;
   }
   out << "]";
@@ -283,7 +278,7 @@
   }
 
   out << ">(";
-  if (!EmitExpression(out, expr->expr())) {
+  if (!EmitExpression(out, expr->expr)) {
     return false;
   }
 
@@ -294,13 +289,13 @@
 bool GeneratorImpl::EmitAssign(ast::AssignmentStatement* stmt) {
   auto out = line();
 
-  if (!EmitExpression(out, stmt->lhs())) {
+  if (!EmitExpression(out, stmt->lhs)) {
     return false;
   }
 
   out << " = ";
 
-  if (!EmitExpression(out, stmt->rhs())) {
+  if (!EmitExpression(out, stmt->rhs)) {
     return false;
   }
 
@@ -313,7 +308,7 @@
   auto emit_op = [&] {
     out << " ";
 
-    switch (expr->op()) {
+    switch (expr->op) {
       case ast::BinaryOp::kAnd:
         out << "&";
         break;
@@ -402,19 +397,19 @@
     return {};
   };
 
-  auto* lhs_type = TypeOf(expr->lhs())->UnwrapRef();
-  auto* rhs_type = TypeOf(expr->rhs())->UnwrapRef();
+  auto* lhs_type = TypeOf(expr->lhs)->UnwrapRef();
+  auto* rhs_type = TypeOf(expr->rhs)->UnwrapRef();
 
   // Handle fmod
-  if (expr->op() == ast::BinaryOp::kModulo &&
+  if (expr->op == ast::BinaryOp::kModulo &&
       lhs_type->is_float_scalar_or_vector()) {
     out << "fmod";
     ScopedParen sp(out);
-    if (!EmitExpression(out, expr->lhs())) {
+    if (!EmitExpression(out, expr->lhs)) {
       return false;
     }
     out << ", ";
-    if (!EmitExpression(out, expr->rhs())) {
+    if (!EmitExpression(out, expr->rhs)) {
       return false;
     }
     return true;
@@ -439,7 +434,7 @@
     {
       ScopedBitCast lhs_uint_cast(this, out, lhs_type,
                                   unsigned_type_of(target_type));
-      if (!EmitExpression(out, expr->lhs())) {
+      if (!EmitExpression(out, expr->lhs)) {
         return false;
       }
     }
@@ -449,7 +444,7 @@
     {
       ScopedBitCast rhs_uint_cast(this, out, rhs_type,
                                   unsigned_type_of(target_type));
-      if (!EmitExpression(out, expr->rhs())) {
+      if (!EmitExpression(out, expr->rhs)) {
         return false;
       }
     }
@@ -468,14 +463,14 @@
     {
       ScopedBitCast lhs_uint_cast(this, out, lhs_type,
                                   unsigned_type_of(lhs_type));
-      if (!EmitExpression(out, expr->lhs())) {
+      if (!EmitExpression(out, expr->lhs)) {
         return false;
       }
     }
     if (!emit_op()) {
       return false;
     }
-    if (!EmitExpression(out, expr->rhs())) {
+    if (!EmitExpression(out, expr->rhs)) {
       return false;
     }
     return true;
@@ -483,13 +478,13 @@
 
   // Emit as usual
   ScopedParen sp(out);
-  if (!EmitExpression(out, expr->lhs())) {
+  if (!EmitExpression(out, expr->lhs)) {
     return false;
   }
   if (!emit_op()) {
     return false;
   }
-  if (!EmitExpression(out, expr->rhs())) {
+  if (!EmitExpression(out, expr->rhs)) {
     return false;
   }
 
@@ -502,21 +497,21 @@
 }
 
 bool GeneratorImpl::EmitCall(std::ostream& out, ast::CallExpression* expr) {
-  auto* ident = expr->func();
+  auto* ident = expr->func;
   auto* call = program_->Sem().Get(expr);
   if (auto* intrinsic = call->Target()->As<sem::Intrinsic>()) {
     return EmitIntrinsicCall(out, expr, intrinsic);
   }
 
-  auto* func = program_->AST().Functions().Find(ident->symbol());
+  auto* func = program_->AST().Functions().Find(ident->symbol);
   if (func == nullptr) {
     diagnostics_.add_error(diag::System::Writer,
                            "Unable to find function: " +
-                               program_->Symbols().NameFor(ident->symbol()));
+                               program_->Symbols().NameFor(ident->symbol));
     return false;
   }
 
-  out << program_->Symbols().NameFor(ident->symbol()) << "(";
+  out << program_->Symbols().NameFor(ident->symbol) << "(";
 
   bool first = true;
   auto* func_sem = program_->Sem().Get(func);
@@ -526,7 +521,7 @@
       out << ", ";
     }
     first = false;
-    out << program_->Symbols().NameFor(var->Declaration()->symbol());
+    out << program_->Symbols().NameFor(var->Declaration()->symbol);
   }
 
   for (const auto& data : func_sem->ReferencedStorageBufferVariables()) {
@@ -535,10 +530,10 @@
       out << ", ";
     }
     first = false;
-    out << program_->Symbols().NameFor(var->Declaration()->symbol());
+    out << program_->Symbols().NameFor(var->Declaration()->symbol);
   }
 
-  const auto& args = expr->args();
+  const auto& args = expr->args;
   for (auto* arg : args) {
     if (!first) {
       out << ", ";
@@ -580,7 +575,7 @@
       } else {
         out << "float2(as_type<half2>(";
       }
-      if (!EmitExpression(out, expr->args()[0])) {
+      if (!EmitExpression(out, expr->args[0])) {
         return false;
       }
       out << "))";
@@ -598,14 +593,14 @@
     }
     case sem::IntrinsicType::kIgnore: {
       out << "(void) ";
-      if (!EmitExpression(out, expr->args()[0])) {
+      if (!EmitExpression(out, expr->args[0])) {
         return false;
       }
       return true;
     }
 
     case sem::IntrinsicType::kLength: {
-      auto* sem = builder_.Sem().Get(expr->args()[0]);
+      auto* sem = builder_.Sem().Get(expr->args[0]);
       if (sem->Type()->UnwrapRef()->is_scalar()) {
         // Emulate scalar overload using fabs(x).
         name = "fabs";
@@ -614,16 +609,16 @@
     }
 
     case sem::IntrinsicType::kDistance: {
-      auto* sem = builder_.Sem().Get(expr->args()[0]);
+      auto* sem = builder_.Sem().Get(expr->args[0]);
       if (sem->Type()->UnwrapRef()->is_scalar()) {
         // Emulate scalar overload using fabs(x - y);
         out << "fabs";
         ScopedParen sp(out);
-        if (!EmitExpression(out, expr->args()[0])) {
+        if (!EmitExpression(out, expr->args[0])) {
           return false;
         }
         out << " - ";
-        if (!EmitExpression(out, expr->args()[1])) {
+        if (!EmitExpression(out, expr->args[1])) {
           return false;
         }
         return true;
@@ -642,8 +637,7 @@
   out << name << "(";
 
   bool first = true;
-  const auto& args = expr->args();
-  for (auto* arg : args) {
+  for (auto* arg : expr->args) {
     if (!first) {
       out << ", ";
     }
@@ -665,8 +659,8 @@
     out << name;
     {
       ScopedParen sp(out);
-      for (size_t i = 0; i < expr->args().size(); i++) {
-        auto* arg = expr->args()[i];
+      for (size_t i = 0; i < expr->args.size(); i++) {
+        auto* arg = expr->args[i];
         if (i > 0) {
           out << ", ";
         }
@@ -713,7 +707,7 @@
       return call("atomic_exchange_explicit", true);
 
     case sem::IntrinsicType::kAtomicCompareExchangeWeak: {
-      auto* ptr_ty = TypeOf(expr->args()[0])->UnwrapRef()->As<sem::Pointer>();
+      auto* ptr_ty = TypeOf(expr->args[0])->UnwrapRef()->As<sem::Pointer>();
       auto sc = ptr_ty->StorageClass();
 
       auto func = utils::GetOrCreate(
@@ -765,7 +759,7 @@
   using Usage = sem::ParameterUsage;
 
   auto& signature = intrinsic->Signature();
-  auto arguments = expr->args();
+  auto arguments = expr->args;
 
   // Returns the argument with the given usage
   auto arg = [&](Usage usage) {
@@ -1236,14 +1230,14 @@
   if (stmt->IsDefault()) {
     line() << "default: {";
   } else {
-    for (auto* selector : stmt->selectors()) {
+    for (auto* selector : stmt->selectors) {
       auto out = line();
       out << "case ";
       if (!EmitLiteral(out, selector)) {
         return false;
       }
       out << ":";
-      if (selector == stmt->selectors().back()) {
+      if (selector == stmt->selectors.back()) {
         out << " {";
       }
     }
@@ -1252,13 +1246,13 @@
   {
     ScopedIndent si(this);
 
-    for (auto* s : *stmt->body()) {
+    for (auto* s : stmt->body->statements) {
       if (!EmitStatement(s)) {
         return false;
       }
     }
 
-    if (!last_is_break_or_fallthrough(stmt->body())) {
+    if (!last_is_break_or_fallthrough(stmt->body)) {
       line() << "break;";
     }
   }
@@ -1299,7 +1293,7 @@
   }
 
   int i = 0;
-  for (auto* e : expr->values()) {
+  for (auto* e : expr->values) {
     if (i > 0) {
       out << ", ";
     }
@@ -1307,7 +1301,7 @@
     if (auto* struct_ty = type->As<sem::Struct>()) {
       // Emit field designators for structures to account for padding members.
       auto* member = struct_ty->Members()[i]->Declaration();
-      auto name = program_->Symbols().NameFor(member->symbol());
+      auto name = program_->Symbols().NameFor(member->symbol);
       out << "." << name << "=";
     }
 
@@ -1366,19 +1360,19 @@
 bool GeneratorImpl::EmitScalarConstructor(
     std::ostream& out,
     ast::ScalarConstructorExpression* expr) {
-  return EmitLiteral(out, expr->literal());
+  return EmitLiteral(out, expr->literal);
 }
 
 bool GeneratorImpl::EmitLiteral(std::ostream& out, ast::Literal* lit) {
   if (auto* l = lit->As<ast::BoolLiteral>()) {
-    out << (l->IsTrue() ? "true" : "false");
+    out << (l->value ? "true" : "false");
   } else if (auto* fl = lit->As<ast::FloatLiteral>()) {
-    if (std::isinf(fl->value())) {
-      out << (fl->value() >= 0 ? "INFINITY" : "-INFINITY");
-    } else if (std::isnan(fl->value())) {
+    if (std::isinf(fl->value)) {
+      out << (fl->value >= 0 ? "INFINITY" : "-INFINITY");
+    } else if (std::isnan(fl->value)) {
       out << "NAN";
     } else {
-      out << FloatToString(fl->value()) << "f";
+      out << FloatToString(fl->value) << "f";
     }
   } else if (auto* sl = lit->As<ast::SintLiteral>()) {
     // MSL (and C++) parse `-2147483648` as a `long` because it parses unary
@@ -1387,13 +1381,13 @@
     // issues with `long` to `int` casts, emit `(2147483647 - 1)` instead, which
     // ensures the expression type is `int`.
     const auto int_min = std::numeric_limits<int32_t>::min();
-    if (sl->value_as_i32() == int_min) {
+    if (sl->ValueAsI32() == int_min) {
       out << "(" << int_min + 1 << " - 1)";
     } else {
-      out << sl->value();
+      out << sl->value;
     }
   } else if (auto* ul = lit->As<ast::UintLiteral>()) {
-    out << ul->value() << "u";
+    out << ul->value << "u";
   } else {
     diagnostics_.add_error(diag::System::Writer, "unknown literal type");
     return false;
@@ -1458,7 +1452,7 @@
     if (!EmitType(out, func_sem->ReturnType(), "")) {
       return false;
     }
-    out << " " << program_->Symbols().NameFor(func->symbol()) << "(";
+    out << " " << program_->Symbols().NameFor(func->symbol) << "(";
 
     bool first = true;
     for (const auto& data : func_sem->ReferencedUniformVariables()) {
@@ -1473,7 +1467,7 @@
       if (!EmitType(out, var->Type()->UnwrapRef(), "")) {
         return false;
       }
-      out << "& " << program_->Symbols().NameFor(var->Declaration()->symbol());
+      out << "& " << program_->Symbols().NameFor(var->Declaration()->symbol);
     }
 
     for (const auto& data : func_sem->ReferencedStorageBufferVariables()) {
@@ -1491,10 +1485,10 @@
       if (!EmitType(out, var->Type()->UnwrapRef(), "")) {
         return false;
       }
-      out << "& " << program_->Symbols().NameFor(var->Declaration()->symbol());
+      out << "& " << program_->Symbols().NameFor(var->Declaration()->symbol);
     }
 
-    for (auto* v : func->params()) {
+    for (auto* v : func->params) {
       if (!first) {
         out << ", ";
       }
@@ -1503,20 +1497,20 @@
       auto* type = program_->Sem().Get(v)->Type();
 
       std::string param_name =
-          "const " + program_->Symbols().NameFor(v->symbol());
+          "const " + program_->Symbols().NameFor(v->symbol);
       if (!EmitType(out, type, param_name)) {
         return false;
       }
       // Parameter name is output as part of the type for arrays and pointers.
       if (!type->Is<sem::Array>() && !type->Is<sem::Pointer>()) {
-        out << " " << program_->Symbols().NameFor(v->symbol());
+        out << " " << program_->Symbols().NameFor(v->symbol);
       }
     }
 
     out << ") {";
   }
 
-  if (!EmitStatementsWithIndent(func->body()->statements())) {
+  if (!EmitStatementsWithIndent(func->body->statements)) {
     return false;
   }
 
@@ -1592,18 +1586,18 @@
 
 bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) {
   auto* func_sem = program_->Sem().Get(func);
-  auto func_name = program_->Symbols().NameFor(func->symbol());
+  auto func_name = program_->Symbols().NameFor(func->symbol);
 
   {
     auto out = line();
 
-    EmitStage(out, func->pipeline_stage());
-    out << " " << func->return_type()->FriendlyName(program_->Symbols());
+    EmitStage(out, func->PipelineStage());
+    out << " " << func->return_type->FriendlyName(program_->Symbols());
     out << " " << func_name << "(";
 
     // Emit entry point parameters.
     bool first = true;
-    for (auto* var : func->params()) {
+    for (auto* var : func->params) {
       if (!first) {
         out << ", ";
       }
@@ -1611,7 +1605,7 @@
 
       auto* type = program_->Sem().Get(var)->Type()->UnwrapRef();
 
-      auto param_name = program_->Symbols().NameFor(var->symbol());
+      auto param_name = program_->Symbols().NameFor(var->symbol);
       if (!EmitType(out, type, param_name)) {
         return false;
       }
@@ -1623,39 +1617,39 @@
       if (type->Is<sem::Struct>()) {
         out << " [[stage_in]]";
       } else if (type->is_handle()) {
-        auto bp = var->binding_point();
+        auto bp = var->BindingPoint();
         if (bp.group == nullptr || bp.binding == nullptr) {
           TINT_ICE(Writer, diagnostics_)
               << "missing binding attributes for entry point parameter";
           return false;
         }
-        if (bp.group->value() != 0) {
+        if (bp.group->value != 0) {
           TINT_ICE(Writer, diagnostics_)
               << "encountered non-zero resource group index (use "
                  "BindingRemapper to fix)";
           return false;
         }
-        if (var->type()->Is<ast::Sampler>()) {
-          out << " [[sampler(" << bp.binding->value() << ")]]";
-        } else if (var->type()->Is<ast::Texture>()) {
-          out << " [[texture(" << bp.binding->value() << ")]]";
+        if (var->type->Is<ast::Sampler>()) {
+          out << " [[sampler(" << bp.binding->value << ")]]";
+        } else if (var->type->Is<ast::Texture>()) {
+          out << " [[texture(" << bp.binding->value << ")]]";
         } else {
           TINT_ICE(Writer, diagnostics_)
               << "invalid handle type entry point parameter";
           return false;
         }
-      } else if (auto* ptr = var->type()->As<ast::Pointer>()) {
-        if (ptr->storage_class() == ast::StorageClass::kWorkgroup) {
+      } else if (auto* ptr = var->type->As<ast::Pointer>()) {
+        if (ptr->storage_class == ast::StorageClass::kWorkgroup) {
           auto& allocations = workgroup_allocations_[func_name];
           out << " [[threadgroup(" << allocations.size() << ")]]";
-          allocations.push_back(program_->Sem().Get(ptr->type())->Size());
+          allocations.push_back(program_->Sem().Get(ptr->type)->Size());
         } else {
           TINT_ICE(Writer, diagnostics_)
               << "invalid pointer storage class for entry point parameter";
           return false;
         }
       } else {
-        auto& decos = var->decorations();
+        auto& decos = var->decorations;
         bool builtin_found = false;
         for (auto* deco : decos) {
           auto* builtin = deco->As<ast::BuiltinDecoration>();
@@ -1665,7 +1659,7 @@
 
           builtin_found = true;
 
-          auto attr = builtin_to_attribute(builtin->value());
+          auto attr = builtin_to_attribute(builtin->builtin);
           if (attr.empty()) {
             diagnostics_.add_error(diag::System::Writer, "unknown builtin");
             return false;
@@ -1693,7 +1687,7 @@
         diagnostics_.add_error(
             diag::System::Writer,
             "unable to find binding information for uniform: " +
-                program_->Symbols().NameFor(var->Declaration()->symbol()));
+                program_->Symbols().NameFor(var->Declaration()->symbol));
         return false;
       }
       // auto* set = data.second.set;
@@ -1704,8 +1698,8 @@
       if (!EmitType(out, var->Type()->UnwrapRef(), "")) {
         return false;
       }
-      out << "& " << program_->Symbols().NameFor(var->Declaration()->symbol())
-          << " [[buffer(" << binding->value() << ")]]";
+      out << "& " << program_->Symbols().NameFor(var->Declaration()->symbol)
+          << " [[buffer(" << binding->value << ")]]";
     }
 
     for (auto data : func_sem->ReferencedStorageBufferVariables()) {
@@ -1729,8 +1723,8 @@
       if (!EmitType(out, var->Type()->UnwrapRef(), "")) {
         return false;
       }
-      out << "& " << program_->Symbols().NameFor(var->Declaration()->symbol())
-          << " [[buffer(" << binding->value() << ")]]";
+      out << "& " << program_->Symbols().NameFor(var->Declaration()->symbol)
+          << " [[buffer(" << binding->value << ")]]";
     }
 
     out << ") {";
@@ -1739,11 +1733,11 @@
   {
     ScopedIndent si(this);
 
-    if (!EmitStatements(func->body()->statements())) {
+    if (!EmitStatements(func->body->statements)) {
       return false;
     }
 
-    if (!Is<ast::ReturnStatement>(func->get_last_statement())) {
+    if (!Is<ast::ReturnStatement>(func->body->Last())) {
       ast::ReturnStatement ret(ProgramID{}, Source{});
       if (!EmitStatement(&ret)) {
         return false;
@@ -1757,14 +1751,14 @@
 
 bool GeneratorImpl::EmitIdentifier(std::ostream& out,
                                    ast::IdentifierExpression* expr) {
-  out << program_->Symbols().NameFor(expr->symbol());
+  out << program_->Symbols().NameFor(expr->symbol);
   return true;
 }
 
 bool GeneratorImpl::EmitLoop(ast::LoopStatement* stmt) {
   auto emit_continuing = [this, stmt]() {
-    if (stmt->has_continuing()) {
-      if (!EmitBlock(stmt->continuing())) {
+    if (stmt->continuing && !stmt->continuing->Empty()) {
+      if (!EmitBlock(stmt->continuing)) {
         return false;
       }
     }
@@ -1775,7 +1769,7 @@
   line() << "while (true) {";
   {
     ScopedIndent si(this);
-    if (!EmitStatements(stmt->body()->statements())) {
+    if (!EmitStatements(stmt->body->statements)) {
       return false;
     }
     if (!emit_continuing()) {
@@ -1789,7 +1783,7 @@
 
 bool GeneratorImpl::EmitForLoop(ast::ForLoopStatement* stmt) {
   TextBuffer init_buf;
-  if (auto* init = stmt->initializer()) {
+  if (auto* init = stmt->initializer) {
     TINT_SCOPED_ASSIGNMENT(current_buffer_, &init_buf);
     if (!EmitStatement(init)) {
       return false;
@@ -1798,7 +1792,7 @@
 
   TextBuffer cond_pre;
   std::stringstream cond_buf;
-  if (auto* cond = stmt->condition()) {
+  if (auto* cond = stmt->condition) {
     TINT_SCOPED_ASSIGNMENT(current_buffer_, &cond_pre);
     if (!EmitExpression(cond_buf, cond)) {
       return false;
@@ -1806,7 +1800,7 @@
   }
 
   TextBuffer cont_buf;
-  if (auto* cont = stmt->continuing()) {
+  if (auto* cont = stmt->continuing) {
     TINT_SCOPED_ASSIGNMENT(current_buffer_, &cont_buf);
     if (!EmitStatement(cont)) {
       return false;
@@ -1822,7 +1816,7 @@
   // as a `while(true)` loop, then declare the initializer statement(s) before
   // the loop in a new block.
   bool nest_in_block =
-      init_buf.lines.size() > 1 || (stmt->initializer() && emit_as_loop);
+      init_buf.lines.size() > 1 || (stmt->initializer && emit_as_loop);
   if (nest_in_block) {
     line() << "{";
     increment_indent();
@@ -1850,12 +1844,12 @@
       line() << "}";
     });
 
-    if (stmt->condition()) {
+    if (stmt->condition) {
       current_buffer_->Append(cond_pre);
       line() << "if (!(" << cond_buf.str() << ")) { break; }";
     }
 
-    if (!EmitStatements(stmt->body()->statements())) {
+    if (!EmitStatements(stmt->body->statements)) {
       return false;
     }
 
@@ -1887,7 +1881,7 @@
     {
       auto emit_continuing = [] { return true; };
       TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);
-      if (!EmitStatementsWithIndent(stmt->body()->statements())) {
+      if (!EmitStatementsWithIndent(stmt->body->statements)) {
         return false;
       }
     }
@@ -1908,25 +1902,25 @@
   {
     auto out = line();
     out << "if (";
-    if (!EmitExpression(out, stmt->condition())) {
+    if (!EmitExpression(out, stmt->condition)) {
       return false;
     }
     out << ") {";
   }
 
-  if (!EmitStatementsWithIndent(stmt->body()->statements())) {
+  if (!EmitStatementsWithIndent(stmt->body->statements)) {
     return false;
   }
 
-  for (auto* e : stmt->else_statements()) {
-    if (e->HasCondition()) {
+  for (auto* e : stmt->else_statements) {
+    if (e->condition) {
       line() << "} else {";
       increment_indent();
 
       {
         auto out = line();
         out << "if (";
-        if (!EmitExpression(out, e->condition())) {
+        if (!EmitExpression(out, e->condition)) {
           return false;
         }
         out << ") {";
@@ -1935,15 +1929,15 @@
       line() << "} else {";
     }
 
-    if (!EmitStatementsWithIndent(e->body()->statements())) {
+    if (!EmitStatementsWithIndent(e->body->statements)) {
       return false;
     }
   }
 
   line() << "}";
 
-  for (auto* e : stmt->else_statements()) {
-    if (e->HasCondition()) {
+  for (auto* e : stmt->else_statements) {
+    if (e->condition) {
       decrement_indent();
       line() << "}";
     }
@@ -1954,14 +1948,14 @@
 bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
                                        ast::MemberAccessorExpression* expr) {
   bool paren_lhs =
-      !expr->structure()
+      !expr->structure
            ->IsAnyOf<ast::ArrayAccessorExpression, ast::CallExpression,
                      ast::IdentifierExpression, ast::MemberAccessorExpression,
                      ast::TypeConstructorExpression>();
   if (paren_lhs) {
     out << "(";
   }
-  if (!EmitExpression(out, expr->structure())) {
+  if (!EmitExpression(out, expr->structure)) {
     return false;
   }
   if (paren_lhs) {
@@ -1972,8 +1966,8 @@
 
   // Swizzles get written out directly
   if (program_->Sem().Get(expr)->Is<sem::Swizzle>()) {
-    out << program_->Symbols().NameFor(expr->member()->symbol());
-  } else if (!EmitExpression(out, expr->member())) {
+    out << program_->Symbols().NameFor(expr->member->symbol);
+  } else if (!EmitExpression(out, expr->member)) {
     return false;
   }
 
@@ -1983,9 +1977,9 @@
 bool GeneratorImpl::EmitReturn(ast::ReturnStatement* stmt) {
   auto out = line();
   out << "return";
-  if (stmt->has_value()) {
+  if (stmt->value) {
     out << " ";
-    if (!EmitExpression(out, stmt->value())) {
+    if (!EmitExpression(out, stmt->value)) {
       return false;
     }
   }
@@ -1996,7 +1990,7 @@
 bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
   line() << "{";
 
-  if (!EmitStatementsWithIndent(stmt->statements())) {
+  if (!EmitStatementsWithIndent(stmt->statements)) {
     return false;
   }
 
@@ -2017,7 +2011,7 @@
   }
   if (auto* c = stmt->As<ast::CallStatement>()) {
     auto out = line();
-    if (!EmitCall(out, c->expr())) {
+    if (!EmitCall(out, c->expr)) {
       return false;
     }
     out << ";";
@@ -2049,7 +2043,7 @@
     return EmitSwitch(s);
   }
   if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
-    auto* var = program_->Sem().Get(v->variable());
+    auto* var = program_->Sem().Get(v->variable);
     return EmitVariable(var);
   }
 
@@ -2077,7 +2071,7 @@
   {
     auto out = line();
     out << "switch(";
-    if (!EmitExpression(out, stmt->condition())) {
+    if (!EmitExpression(out, stmt->condition)) {
       return false;
     }
     out << ") {";
@@ -2085,7 +2079,7 @@
 
   {
     ScopedIndent si(this);
-    for (auto* s : stmt->body()) {
+    for (auto* s : stmt->body) {
       if (!EmitCase(s)) {
         return false;
       }
@@ -2438,9 +2432,9 @@
 
     // Emit decorations
     if (auto* decl = mem->Declaration()) {
-      for (auto* deco : decl->decorations()) {
+      for (auto* deco : decl->decorations) {
         if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
-          auto attr = builtin_to_attribute(builtin->value());
+          auto attr = builtin_to_attribute(builtin->builtin);
           if (attr.empty()) {
             diagnostics_.add_error(diag::System::Writer, "unknown builtin");
             return false;
@@ -2455,23 +2449,23 @@
 
           if (pipeline_stage_uses.count(
                   sem::PipelineStageUsage::kVertexInput)) {
-            out << " [[attribute(" + std::to_string(loc->value()) + ")]]";
+            out << " [[attribute(" + std::to_string(loc->value) + ")]]";
           } else if (pipeline_stage_uses.count(
                          sem::PipelineStageUsage::kVertexOutput)) {
-            out << " [[user(locn" + std::to_string(loc->value()) + ")]]";
+            out << " [[user(locn" + std::to_string(loc->value) + ")]]";
           } else if (pipeline_stage_uses.count(
                          sem::PipelineStageUsage::kFragmentInput)) {
-            out << " [[user(locn" + std::to_string(loc->value()) + ")]]";
+            out << " [[user(locn" + std::to_string(loc->value) + ")]]";
           } else if (pipeline_stage_uses.count(
                          sem::PipelineStageUsage::kFragmentOutput)) {
-            out << " [[color(" + std::to_string(loc->value()) + ")]]";
+            out << " [[color(" + std::to_string(loc->value) + ")]]";
           } else {
             TINT_ICE(Writer, diagnostics_)
                 << "invalid use of location decoration";
           }
         } else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) {
-          auto attr = interpolation_to_attribute(interpolate->type(),
-                                                 interpolate->sampling());
+          auto attr = interpolation_to_attribute(interpolate->type,
+                                                 interpolate->sampling);
           if (attr.empty()) {
             diagnostics_.add_error(diag::System::Writer,
                                    "unknown interpolation attribute");
@@ -2485,7 +2479,7 @@
                                   ast::StructMemberAlignDecoration,
                                   ast::StructMemberSizeDecoration>()) {
           TINT_ICE(Writer, diagnostics_)
-              << "unhandled struct member attribute: " << deco->name();
+              << "unhandled struct member attribute: " << deco->Name();
         }
       }
     }
@@ -2519,8 +2513,8 @@
                                 ast::UnaryOpExpression* expr) {
   // Handle `-e` when `e` is signed, so that we ensure that if `e` is the
   // largest negative value, it returns `e`.
-  auto* expr_type = TypeOf(expr->expr())->UnwrapRef();
-  if (expr->op() == ast::UnaryOp::kNegation &&
+  auto* expr_type = TypeOf(expr->expr)->UnwrapRef();
+  if (expr->op == ast::UnaryOp::kNegation &&
       expr_type->is_signed_scalar_or_vector()) {
     auto fn =
         utils::GetOrCreate(unary_minus_funcs_, expr_type, [&]() -> std::string {
@@ -2557,14 +2551,14 @@
         });
 
     out << fn << "(";
-    if (!EmitExpression(out, expr->expr())) {
+    if (!EmitExpression(out, expr->expr)) {
       return false;
     }
     out << ")";
     return true;
   }
 
-  switch (expr->op()) {
+  switch (expr->op) {
     case ast::UnaryOp::kAddressOf:
       out << "&";
       break;
@@ -2583,7 +2577,7 @@
   }
   out << "(";
 
-  if (!EmitExpression(out, expr->expr())) {
+  if (!EmitExpression(out, expr->expr)) {
     return false;
   }
 
@@ -2595,7 +2589,7 @@
 bool GeneratorImpl::EmitVariable(const sem::Variable* var) {
   auto* decl = var->Declaration();
 
-  for (auto* deco : decl->decorations()) {
+  for (auto* deco : decl->decorations) {
     if (!deco->Is<ast::InternalDecoration>()) {
       TINT_ICE(Writer, diagnostics_) << "unexpected variable decoration";
       return false;
@@ -2622,8 +2616,8 @@
 
   auto* type = var->Type()->UnwrapRef();
 
-  std::string name = program_->Symbols().NameFor(decl->symbol());
-  if (decl->is_const()) {
+  std::string name = program_->Symbols().NameFor(decl->symbol);
+  if (decl->is_const) {
     name = "const " + name;
   }
   if (!EmitType(out, type, name)) {
@@ -2634,9 +2628,9 @@
     out << " " << name;
   }
 
-  if (decl->constructor() != nullptr) {
+  if (decl->constructor != nullptr) {
     out << " = ";
-    if (!EmitExpression(out, decl->constructor())) {
+    if (!EmitExpression(out, decl->constructor)) {
       return false;
     }
   } else if (var->StorageClass() == ast::StorageClass::kPrivate ||
@@ -2653,14 +2647,14 @@
 }
 
 bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
-  for (auto* d : var->decorations()) {
+  for (auto* d : var->decorations) {
     if (!d->Is<ast::OverrideDecoration>()) {
       diagnostics_.add_error(diag::System::Writer,
                              "Decorated const values not valid");
       return false;
     }
   }
-  if (!var->is_const()) {
+  if (!var->is_const) {
     diagnostics_.add_error(diag::System::Writer, "Expected a const value");
     return false;
   }
@@ -2668,19 +2662,19 @@
   auto out = line();
   out << "constant ";
   auto* type = program_->Sem().Get(var)->Type()->UnwrapRef();
-  if (!EmitType(out, type, program_->Symbols().NameFor(var->symbol()))) {
+  if (!EmitType(out, type, program_->Symbols().NameFor(var->symbol))) {
     return false;
   }
   if (!type->Is<sem::Array>()) {
-    out << " " << program_->Symbols().NameFor(var->symbol());
+    out << " " << program_->Symbols().NameFor(var->symbol);
   }
 
   auto* global = program_->Sem().Get<sem::GlobalVariable>(var);
   if (global && global->IsPipelineConstant()) {
     out << " [[function_constant(" << global->ConstantId() << ")]]";
-  } else if (var->constructor() != nullptr) {
+  } else if (var->constructor != nullptr) {
     out << " = ";
-    if (!EmitExpression(out, var->constructor())) {
+    if (!EmitExpression(out, var->constructor)) {
       return false;
     }
   }
@@ -2817,7 +2811,7 @@
   {
     ScopedParen sp(out);
     bool first = true;
-    for (auto* arg : call->args()) {
+    for (auto* arg : call->args) {
       if (!first) {
         out << ", ";
       }
diff --git a/src/writer/msl/generator_impl_case_test.cc b/src/writer/msl/generator_impl_case_test.cc
index 42b9482..7aff221 100644
--- a/src/writer/msl/generator_impl_case_test.cc
+++ b/src/writer/msl/generator_impl_case_test.cc
@@ -31,7 +31,7 @@
 
   gen.increment_indent();
 
-  ASSERT_TRUE(gen.EmitCase(s->body()[0])) << gen.error();
+  ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.error();
   EXPECT_EQ(gen.result(), R"(  case 5: {
     break;
   }
@@ -46,7 +46,7 @@
 
   gen.increment_indent();
 
-  ASSERT_TRUE(gen.EmitCase(s->body()[0])) << gen.error();
+  ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.error();
   EXPECT_EQ(gen.result(), R"(  case 5: {
     break;
   }
@@ -63,7 +63,7 @@
 
   gen.increment_indent();
 
-  ASSERT_TRUE(gen.EmitCase(s->body()[0])) << gen.error();
+  ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.error();
   EXPECT_EQ(gen.result(), R"(  case 5: {
     /* fallthrough */
   }
@@ -80,7 +80,7 @@
 
   gen.increment_indent();
 
-  ASSERT_TRUE(gen.EmitCase(s->body()[0])) << gen.error();
+  ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.error();
   EXPECT_EQ(gen.result(), R"(  case 5:
   case 6: {
     break;
@@ -96,7 +96,7 @@
 
   gen.increment_indent();
 
-  ASSERT_TRUE(gen.EmitCase(s->body()[0])) << gen.error();
+  ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.error();
   EXPECT_EQ(gen.result(), R"(  default: {
     break;
   }
diff --git a/src/writer/msl/generator_impl_intrinsic_texture_test.cc b/src/writer/msl/generator_impl_intrinsic_texture_test.cc
index 5101add..d0b77ea 100644
--- a/src/writer/msl/generator_impl_intrinsic_texture_test.cc
+++ b/src/writer/msl/generator_impl_intrinsic_texture_test.cc
@@ -241,8 +241,8 @@
 TEST_P(MslGeneratorIntrinsicTextureTest, Call) {
   auto param = GetParam();
 
-  param.buildTextureVariable(this);
-  param.buildSamplerVariable(this);
+  param.BuildTextureVariable(this);
+  param.BuildSamplerVariable(this);
 
   auto* call =
       create<ast::CallExpression>(Expr(param.function), param.args(this));
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 0de0335..f37ffd1 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -86,25 +86,20 @@
 }
 
 bool LastIsFallthrough(const ast::BlockStatement* stmts) {
-  return !stmts->empty() && stmts->last()->Is<ast::FallthroughStatement>();
+  return !stmts->Empty() && stmts->Last()->Is<ast::FallthroughStatement>();
 }
 
 // A terminator is anything which will cause a SPIR-V terminator to be emitted.
 // This means things like breaks, fallthroughs and continues which all emit an
 // OpBranch or return for the OpReturn emission.
 bool LastIsTerminator(const ast::BlockStatement* stmts) {
-  if (stmts->empty()) {
-    return false;
-  }
-
-  auto* last = stmts->last();
-  if (last->Is<ast::BreakStatement>() || last->Is<ast::ContinueStatement>() ||
-      last->Is<ast::DiscardStatement>() || last->Is<ast::ReturnStatement>() ||
-      last->Is<ast::FallthroughStatement>()) {
+  if (IsAnyOf<ast::BreakStatement, ast::ContinueStatement,
+              ast::DiscardStatement, ast::ReturnStatement,
+              ast::FallthroughStatement>(stmts->Last())) {
     return true;
   }
 
-  if (auto* block = last->As<ast::BlockStatement>()) {
+  if (auto* block = As<ast::BlockStatement>(stmts->Last())) {
     return LastIsTerminator(block);
   }
 
@@ -393,17 +388,17 @@
 }
 
 bool Builder::GenerateAssignStatement(ast::AssignmentStatement* assign) {
-  auto lhs_id = GenerateExpression(assign->lhs());
+  auto lhs_id = GenerateExpression(assign->lhs);
   if (lhs_id == 0) {
     return false;
   }
-  auto rhs_id = GenerateExpression(assign->rhs());
+  auto rhs_id = GenerateExpression(assign->rhs);
   if (rhs_id == 0) {
     return false;
   }
 
   // If the thing we're assigning is a reference then we must load it first.
-  auto* type = TypeOf(assign->rhs());
+  auto* type = TypeOf(assign->rhs);
   rhs_id = GenerateLoadIfNeeded(type, rhs_id);
 
   return GenerateStore(lhs_id, rhs_id);
@@ -444,7 +439,7 @@
 }
 
 bool Builder::GenerateEntryPoint(ast::Function* func, uint32_t id) {
-  auto stage = pipeline_stage_to_execution_model(func->pipeline_stage());
+  auto stage = pipeline_stage_to_execution_model(func->PipelineStage());
   if (stage == SpvExecutionModelMax) {
     error_ = "Unknown pipeline stage provided";
     return false;
@@ -452,7 +447,7 @@
 
   OperandList operands = {
       Operand::Int(stage), Operand::Int(id),
-      Operand::String(builder_.Symbols().NameFor(func->symbol()))};
+      Operand::String(builder_.Symbols().NameFor(func->symbol))};
 
   auto* func_sem = builder_.Sem().Get(func);
   for (const auto* var : func_sem->ReferencedModuleVariables()) {
@@ -464,9 +459,9 @@
     }
 
     uint32_t var_id;
-    if (!scope_stack_.get(var->Declaration()->symbol(), &var_id)) {
+    if (!scope_stack_.get(var->Declaration()->symbol, &var_id)) {
       error_ = "unable to find ID for global variable: " +
-               builder_.Symbols().NameFor(var->Declaration()->symbol());
+               builder_.Symbols().NameFor(var->Declaration()->symbol);
       return false;
     }
 
@@ -481,11 +476,11 @@
   auto* func_sem = builder_.Sem().Get(func);
 
   // WGSL fragment shader origin is upper left
-  if (func->pipeline_stage() == ast::PipelineStage::kFragment) {
+  if (func->PipelineStage() == ast::PipelineStage::kFragment) {
     push_execution_mode(
         spv::Op::OpExecutionMode,
         {Operand::Int(id), Operand::Int(SpvExecutionModeOriginUpperLeft)});
-  } else if (func->pipeline_stage() == ast::PipelineStage::kCompute) {
+  } else if (func->PipelineStage() == ast::PipelineStage::kCompute) {
     auto& wgsize = func_sem->workgroup_size();
 
     // Check if the workgroup_size uses pipeline-overridable constants.
@@ -548,7 +543,7 @@
   }
 
   for (auto builtin : func_sem->ReferencedBuiltinVariables()) {
-    if (builtin.second->value() == ast::Builtin::kFragDepth) {
+    if (builtin.second->builtin == ast::Builtin::kFragDepth) {
       push_execution_mode(
           spv::Op::OpExecutionMode,
           {Operand::Int(id), Operand::Int(SpvExecutionModeDepthReplacing)});
@@ -601,7 +596,7 @@
 
   push_debug(spv::Op::OpName,
              {Operand::Int(func_id),
-              Operand::String(builder_.Symbols().NameFor(func_ast->symbol()))});
+              Operand::String(builder_.Symbols().NameFor(func_ast->symbol))});
 
   auto ret_id = GenerateTypeIfNeeded(func->ReturnType());
   if (ret_id == 0) {
@@ -627,16 +622,16 @@
 
     push_debug(spv::Op::OpName, {Operand::Int(param_id),
                                  Operand::String(builder_.Symbols().NameFor(
-                                     param->Declaration()->symbol()))});
+                                     param->Declaration()->symbol))});
     params.push_back(Instruction{spv::Op::OpFunctionParameter,
                                  {Operand::Int(param_type_id), param_op}});
 
-    scope_stack_.set(param->Declaration()->symbol(), param_id);
+    scope_stack_.set(param->Declaration()->symbol, param_id);
   }
 
   push_function(Function{definition_inst, result_op(), std::move(params)});
 
-  for (auto* stmt : *func_ast->body()) {
+  for (auto* stmt : func_ast->body->statements) {
     if (!GenerateStatement(stmt)) {
       return false;
     }
@@ -653,7 +648,7 @@
 
   scope_stack_.pop_scope();
 
-  func_symbol_to_id_[func_ast->symbol()] = func_id;
+  func_symbol_to_id_[func_ast->symbol] = func_id;
 
   return true;
 }
@@ -685,23 +680,23 @@
 
 bool Builder::GenerateFunctionVariable(ast::Variable* var) {
   uint32_t init_id = 0;
-  if (var->has_constructor()) {
-    init_id = GenerateExpression(var->constructor());
+  if (var->constructor) {
+    init_id = GenerateExpression(var->constructor);
     if (init_id == 0) {
       return false;
     }
-    auto* type = TypeOf(var->constructor());
+    auto* type = TypeOf(var->constructor);
     if (type->Is<sem::Reference>()) {
       init_id = GenerateLoadIfNeeded(type, init_id);
     }
   }
 
-  if (var->is_const()) {
-    if (!var->has_constructor()) {
+  if (var->is_const) {
+    if (!var->constructor) {
       error_ = "missing constructor for constant";
       return false;
     }
-    scope_stack_.set(var->symbol(), init_id);
+    scope_stack_.set(var->symbol, init_id);
     spirv_id_to_variable_[init_id] = var;
     return true;
   }
@@ -717,7 +712,7 @@
 
   push_debug(spv::Op::OpName,
              {Operand::Int(var_id),
-              Operand::String(builder_.Symbols().NameFor(var->symbol()))});
+              Operand::String(builder_.Symbols().NameFor(var->symbol))});
 
   // TODO(dsinclair) We could detect if the constructor is fully const and emit
   // an initializer value for the variable instead of doing the OpLoad.
@@ -729,13 +724,13 @@
                      Operand::Int(ConvertStorageClass(sc)),
                      Operand::Int(null_id)});
 
-  if (var->has_constructor()) {
+  if (var->constructor) {
     if (!GenerateStore(var_id, init_id)) {
       return false;
     }
   }
 
-  scope_stack_.set(var->symbol(), var_id);
+  scope_stack_.set(var->symbol, var_id);
   spirv_id_to_variable_[var_id] = var;
 
   return true;
@@ -751,24 +746,24 @@
   auto* type = sem->Type()->UnwrapRef();
 
   uint32_t init_id = 0;
-  if (var->has_constructor()) {
-    if (!var->constructor()->Is<ast::ConstructorExpression>()) {
+  if (var->constructor) {
+    if (!var->constructor->Is<ast::ConstructorExpression>()) {
       error_ = "scalar constructor expected";
       return false;
     }
 
     init_id = GenerateConstructorExpression(
-        var, var->constructor()->As<ast::ConstructorExpression>(), true);
+        var, var->constructor->As<ast::ConstructorExpression>(), true);
     if (init_id == 0) {
       return false;
     }
   }
 
-  if (var->is_const()) {
-    if (!var->has_constructor()) {
+  if (var->is_const) {
+    if (!var->constructor) {
       // Constants must have an initializer unless they have an override
       // decoration.
-      if (!ast::HasDecoration<ast::OverrideDecoration>(var->decorations())) {
+      if (!ast::HasDecoration<ast::OverrideDecoration>(var->decorations)) {
         error_ = "missing constructor for constant";
         return false;
       }
@@ -796,9 +791,9 @@
     }
     push_debug(spv::Op::OpName,
                {Operand::Int(init_id),
-                Operand::String(builder_.Symbols().NameFor(var->symbol()))});
+                Operand::String(builder_.Symbols().NameFor(var->symbol))});
 
-    scope_stack_.set_global(var->symbol(), init_id);
+    scope_stack_.set_global(var->symbol, init_id);
     spirv_id_to_variable_[init_id] = var;
     return true;
   }
@@ -817,12 +812,12 @@
 
   push_debug(spv::Op::OpName,
              {Operand::Int(var_id),
-              Operand::String(builder_.Symbols().NameFor(var->symbol()))});
+              Operand::String(builder_.Symbols().NameFor(var->symbol))});
 
   OperandList ops = {Operand::Int(type_id), result,
                      Operand::Int(ConvertStorageClass(sc))};
 
-  if (var->has_constructor()) {
+  if (var->constructor) {
     ops.push_back(Operand::Int(init_id));
   } else {
     auto* st = type->As<sem::StorageTexture>();
@@ -861,30 +856,30 @@
 
   push_type(spv::Op::OpVariable, std::move(ops));
 
-  for (auto* deco : var->decorations()) {
+  for (auto* deco : var->decorations) {
     if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
       push_annot(spv::Op::OpDecorate,
                  {Operand::Int(var_id), Operand::Int(SpvDecorationBuiltIn),
                   Operand::Int(
-                      ConvertBuiltin(builtin->value(), sem->StorageClass()))});
+                      ConvertBuiltin(builtin->builtin, sem->StorageClass()))});
     } else if (auto* location = deco->As<ast::LocationDecoration>()) {
       push_annot(spv::Op::OpDecorate,
                  {Operand::Int(var_id), Operand::Int(SpvDecorationLocation),
-                  Operand::Int(location->value())});
+                  Operand::Int(location->value)});
     } else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) {
-      AddInterpolationDecorations(var_id, interpolate->type(),
-                                  interpolate->sampling());
+      AddInterpolationDecorations(var_id, interpolate->type,
+                                  interpolate->sampling);
     } else if (deco->Is<ast::InvariantDecoration>()) {
       push_annot(spv::Op::OpDecorate,
                  {Operand::Int(var_id), Operand::Int(SpvDecorationInvariant)});
     } else if (auto* binding = deco->As<ast::BindingDecoration>()) {
       push_annot(spv::Op::OpDecorate,
                  {Operand::Int(var_id), Operand::Int(SpvDecorationBinding),
-                  Operand::Int(binding->value())});
+                  Operand::Int(binding->value)});
     } else if (auto* group = deco->As<ast::GroupDecoration>()) {
       push_annot(spv::Op::OpDecorate, {Operand::Int(var_id),
                                        Operand::Int(SpvDecorationDescriptorSet),
-                                       Operand::Int(group->value())});
+                                       Operand::Int(group->value)});
     } else if (deco->Is<ast::OverrideDecoration>()) {
       // Spec constants are handled elsewhere
     } else if (!deco->Is<ast::InternalDecoration>()) {
@@ -893,18 +888,18 @@
     }
   }
 
-  scope_stack_.set_global(var->symbol(), var_id);
+  scope_stack_.set_global(var->symbol, var_id);
   spirv_id_to_variable_[var_id] = var;
   return true;
 }
 
 bool Builder::GenerateArrayAccessor(ast::ArrayAccessorExpression* expr,
                                     AccessorInfo* info) {
-  auto idx_id = GenerateExpression(expr->idx_expr());
+  auto idx_id = GenerateExpression(expr->index);
   if (idx_id == 0) {
     return 0;
   }
-  auto* type = TypeOf(expr->idx_expr());
+  auto* type = TypeOf(expr->index);
   idx_id = GenerateLoadIfNeeded(type, idx_id);
 
   // If the source is a reference, we access chain into it.
@@ -926,8 +921,8 @@
   auto extract_id = extract.to_i();
 
   // If the index is a literal, we use OpCompositeExtract.
-  if (auto* scalar = expr->idx_expr()->As<ast::ScalarConstructorExpression>()) {
-    auto* literal = scalar->literal()->As<ast::IntLiteral>();
+  if (auto* scalar = expr->index->As<ast::ScalarConstructorExpression>()) {
+    auto* literal = scalar->literal->As<ast::IntLiteral>();
     if (!literal) {
       TINT_ICE(Writer, builder_.Diagnostics())
           << "bad literal in array accessor";
@@ -937,7 +932,7 @@
     if (!push_function_inst(spv::Op::OpCompositeExtract,
                             {Operand::Int(result_type_id), extract,
                              Operand::Int(info->source_id),
-                             Operand::Int(literal->value_as_u32())})) {
+                             Operand::Int(literal->ValueAsU32())})) {
       return false;
     }
 
@@ -1108,10 +1103,10 @@
   while (true) {
     if (auto* array = source->As<ast::ArrayAccessorExpression>()) {
       accessors.insert(accessors.begin(), source);
-      source = array->array();
+      source = array->array;
     } else if (auto* member = source->As<ast::MemberAccessorExpression>()) {
       accessors.insert(accessors.begin(), source);
-      source = member->structure();
+      source = member->structure;
     } else {
       break;
     }
@@ -1169,12 +1164,12 @@
 uint32_t Builder::GenerateIdentifierExpression(
     ast::IdentifierExpression* expr) {
   uint32_t val = 0;
-  if (scope_stack_.get(expr->symbol(), &val)) {
+  if (scope_stack_.get(expr->symbol, &val)) {
     return val;
   }
 
   error_ = "unable to find variable with identifier: " +
-           builder_.Symbols().NameFor(expr->symbol());
+           builder_.Symbols().NameFor(expr->symbol);
   return 0;
 }
 
@@ -1199,13 +1194,13 @@
   auto result = result_op();
   auto result_id = result.to_i();
 
-  auto val_id = GenerateExpression(expr->expr());
+  auto val_id = GenerateExpression(expr->expr);
   if (val_id == 0) {
     return 0;
   }
 
   spv::Op op = spv::Op::OpNop;
-  switch (expr->op()) {
+  switch (expr->op) {
     case ast::UnaryOp::kComplement:
       op = spv::Op::OpNot;
       break;
@@ -1227,7 +1222,7 @@
       return val_id;
   }
 
-  val_id = GenerateLoadIfNeeded(TypeOf(expr->expr()), val_id);
+  val_id = GenerateLoadIfNeeded(TypeOf(expr->expr), val_id);
 
   auto type_id = GenerateTypeIfNeeded(TypeOf(expr));
   if (type_id == 0) {
@@ -1265,7 +1260,7 @@
     ast::ConstructorExpression* expr,
     bool is_global_init) {
   if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) {
-    return GenerateLiteralIfNeeded(var, scalar->literal());
+    return GenerateLiteralIfNeeded(var, scalar->literal);
   }
   if (auto* type = expr->As<ast::TypeConstructorExpression>()) {
     return GenerateTypeConstructorExpression(type, is_global_init);
@@ -1286,8 +1281,8 @@
 
   auto* tc = constructor->As<ast::TypeConstructorExpression>();
   auto* result_type = TypeOf(tc)->UnwrapRef();
-  for (size_t i = 0; i < tc->values().size(); ++i) {
-    auto* e = tc->values()[i];
+  for (size_t i = 0; i < tc->values.size(); ++i) {
+    auto* e = tc->values[i];
 
     if (!e->Is<ast::ConstructorExpression>()) {
       if (is_global_init) {
@@ -1333,7 +1328,7 @@
 uint32_t Builder::GenerateTypeConstructorExpression(
     ast::TypeConstructorExpression* init,
     bool is_global_init) {
-  auto& values = init->values();
+  auto& values = init->values;
 
   auto* result_type = TypeOf(init);
 
@@ -1343,7 +1338,7 @@
   }
 
   std::ostringstream out;
-  out << "__const_" << init->type()->FriendlyName(builder_.Symbols()) << "_";
+  out << "__const_" << init->type->FriendlyName(builder_.Symbols()) << "_";
 
   result_type = result_type->UnwrapRef();
   bool constructor_is_const = is_constructor_const(init, is_global_init);
@@ -1665,16 +1660,16 @@
 
   if (auto* l = lit->As<ast::BoolLiteral>()) {
     constant.kind = ScalarConstant::Kind::kBool;
-    constant.value.b = l->IsTrue();
+    constant.value.b = l->value;
   } else if (auto* sl = lit->As<ast::SintLiteral>()) {
     constant.kind = ScalarConstant::Kind::kI32;
-    constant.value.i32 = sl->value();
+    constant.value.i32 = sl->value;
   } else if (auto* ul = lit->As<ast::UintLiteral>()) {
     constant.kind = ScalarConstant::Kind::kU32;
-    constant.value.u32 = ul->value();
+    constant.value.u32 = ul->value;
   } else if (auto* fl = lit->As<ast::FloatLiteral>()) {
     constant.kind = ScalarConstant::Kind::kF32;
-    constant.value.f32 = fl->value();
+    constant.value.f32 = fl->value;
   } else {
     error_ = "unknown literal type";
     return 0;
@@ -1809,11 +1804,11 @@
 
 uint32_t Builder::GenerateShortCircuitBinaryExpression(
     ast::BinaryExpression* expr) {
-  auto lhs_id = GenerateExpression(expr->lhs());
+  auto lhs_id = GenerateExpression(expr->lhs);
   if (lhs_id == 0) {
     return false;
   }
-  lhs_id = GenerateLoadIfNeeded(TypeOf(expr->lhs()), lhs_id);
+  lhs_id = GenerateLoadIfNeeded(TypeOf(expr->lhs), lhs_id);
 
   // Get the ID of the basic block where control flow will diverge. It's the
   // last basic block generated for the left-hand-side of the operator.
@@ -1853,11 +1848,11 @@
   if (!GenerateLabel(block_id)) {
     return 0;
   }
-  auto rhs_id = GenerateExpression(expr->rhs());
+  auto rhs_id = GenerateExpression(expr->rhs);
   if (rhs_id == 0) {
     return 0;
   }
-  rhs_id = GenerateLoadIfNeeded(TypeOf(expr->rhs()), rhs_id);
+  rhs_id = GenerateLoadIfNeeded(TypeOf(expr->rhs), rhs_id);
 
   // Get the block ID of the last basic block generated for the right-hand-side
   // expression. That block will be an immediate predecessor to the merge block.
@@ -1976,17 +1971,17 @@
     return GenerateShortCircuitBinaryExpression(expr);
   }
 
-  auto lhs_id = GenerateExpression(expr->lhs());
+  auto lhs_id = GenerateExpression(expr->lhs);
   if (lhs_id == 0) {
     return 0;
   }
-  lhs_id = GenerateLoadIfNeeded(TypeOf(expr->lhs()), lhs_id);
+  lhs_id = GenerateLoadIfNeeded(TypeOf(expr->lhs), lhs_id);
 
-  auto rhs_id = GenerateExpression(expr->rhs());
+  auto rhs_id = GenerateExpression(expr->rhs);
   if (rhs_id == 0) {
     return 0;
   }
-  rhs_id = GenerateLoadIfNeeded(TypeOf(expr->rhs()), rhs_id);
+  rhs_id = GenerateLoadIfNeeded(TypeOf(expr->rhs), rhs_id);
 
   auto result = result_op();
   auto result_id = result.to_i();
@@ -1998,8 +1993,8 @@
 
   // Handle int and float and the vectors of those types. Other types
   // should have been rejected by validation.
-  auto* lhs_type = TypeOf(expr->lhs())->UnwrapRef();
-  auto* rhs_type = TypeOf(expr->rhs())->UnwrapRef();
+  auto* lhs_type = TypeOf(expr->lhs)->UnwrapRef();
+  auto* rhs_type = TypeOf(expr->rhs)->UnwrapRef();
 
   // Handle matrix-matrix addition and subtraction
   if ((expr->IsAdd() || expr->IsSubtract()) && lhs_type->is_float_matrix() &&
@@ -2213,7 +2208,7 @@
 
 bool Builder::GenerateBlockStatementWithoutScoping(
     const ast::BlockStatement* stmt) {
-  for (auto* block_stmt : *stmt) {
+  for (auto* block_stmt : stmt->statements) {
     if (!GenerateStatement(block_stmt)) {
       return false;
     }
@@ -2222,7 +2217,7 @@
 }
 
 uint32_t Builder::GenerateCallExpression(ast::CallExpression* expr) {
-  auto* ident = expr->func();
+  auto* ident = expr->func;
   auto* call = builder_.Sem().Get(expr);
   auto* target = call->Target();
   if (auto* intrinsic = target->As<sem::Intrinsic>()) {
@@ -2239,16 +2234,16 @@
 
   OperandList ops = {Operand::Int(type_id), result};
 
-  auto func_id = func_symbol_to_id_[ident->symbol()];
+  auto func_id = func_symbol_to_id_[ident->symbol];
   if (func_id == 0) {
     error_ = "unable to find called function: " +
-             builder_.Symbols().NameFor(ident->symbol());
+             builder_.Symbols().NameFor(ident->symbol);
     return 0;
   }
   ops.push_back(Operand::Int(func_id));
 
   size_t arg_idx = 0;
-  for (auto* arg : expr->args()) {
+  for (auto* arg : expr->args) {
     auto id = GenerateExpression(arg);
     if (id == 0) {
       return 0;
@@ -2313,7 +2308,7 @@
   // and loads it if necessary. Returns 0 on error.
   auto get_param_as_value_id = [&](size_t i,
                                    bool generate_load = true) -> uint32_t {
-    auto* arg = call->args()[i];
+    auto* arg = call->args[i];
     auto* param = intrinsic->Parameters()[i];
     auto val_id = GenerateExpression(arg);
     if (val_id == 0) {
@@ -2346,19 +2341,19 @@
       op = spv::Op::OpAll;
       break;
     case IntrinsicType::kArrayLength: {
-      if (call->args().empty()) {
+      if (call->args.empty()) {
         error_ = "missing param for runtime array length";
         return 0;
       }
-      auto* arg = call->args()[0];
+      auto* arg = call->args[0];
 
       auto* address_of = arg->As<ast::UnaryOpExpression>();
-      if (!address_of || address_of->op() != ast::UnaryOp::kAddressOf) {
+      if (!address_of || address_of->op != ast::UnaryOp::kAddressOf) {
         error_ = "arrayLength() expected pointer to member access, got " +
                  std::string(address_of->TypeInfo().name);
         return 0;
       }
-      auto* array_expr = address_of->expr();
+      auto* array_expr = address_of->expr;
 
       auto* accessor = array_expr->As<ast::MemberAccessorExpression>();
       if (!accessor) {
@@ -2368,13 +2363,13 @@
         return 0;
       }
 
-      auto struct_id = GenerateExpression(accessor->structure());
+      auto struct_id = GenerateExpression(accessor->structure);
       if (struct_id == 0) {
         return 0;
       }
       params.push_back(Operand::Int(struct_id));
 
-      auto* type = TypeOf(accessor->structure())->UnwrapRef();
+      auto* type = TypeOf(accessor->structure)->UnwrapRef();
       if (!type->Is<sem::Struct>()) {
         error_ =
             "invalid type (" + type->type_name() + ") for runtime array length";
@@ -2382,7 +2377,7 @@
       }
       // Runtime array must be the last member in the structure
       params.push_back(Operand::Int(uint32_t(
-          type->As<sem::Struct>()->Declaration()->members().size() - 1)));
+          type->As<sem::Struct>()->Declaration()->members.size() - 1)));
 
       if (!push_function_inst(spv::Op::OpArrayLength, params)) {
         return 0;
@@ -2638,7 +2633,7 @@
     return 0;
   }
 
-  for (size_t i = 0; i < call->args().size(); i++) {
+  for (size_t i = 0; i < call->args.size(); i++) {
     if (auto val_id = get_param_as_value_id(i)) {
       params.emplace_back(Operand::Int(val_id));
     } else {
@@ -2660,7 +2655,7 @@
   using Usage = sem::ParameterUsage;
 
   auto& signature = intrinsic->Signature();
-  auto arguments = call->args();
+  auto arguments = call->args;
 
   // Generates the given expression, returning the operand ID
   auto gen = [&](ast::Expression* expr) {
@@ -3136,18 +3131,18 @@
     return false;
   }
 
-  uint32_t pointer_id = GenerateExpression(call->args()[0]);
+  uint32_t pointer_id = GenerateExpression(call->args[0]);
   if (pointer_id == 0) {
     return false;
   }
 
   uint32_t value_id = 0;
-  if (call->args().size() > 1) {
-    value_id = GenerateExpression(call->args().back());
+  if (call->args.size() > 1) {
+    value_id = GenerateExpression(call->args.back());
     if (value_id == 0) {
       return false;
     }
-    value_id = GenerateLoadIfNeeded(TypeOf(call->args().back()), value_id);
+    value_id = GenerateLoadIfNeeded(TypeOf(call->args.back()), value_id);
     if (value_id == 0) {
       return false;
     }
@@ -3251,12 +3246,12 @@
                                                                value,
                                                            });
     case sem::IntrinsicType::kAtomicCompareExchangeWeak: {
-      auto comparator = GenerateExpression(call->args()[1]);
+      auto comparator = GenerateExpression(call->args[1]);
       if (comparator == 0) {
         return false;
       }
 
-      auto* value_sem_type = TypeOf(call->args()[2]);
+      auto* value_sem_type = TypeOf(call->args[2]);
 
       auto value_type = GenerateTypeIfNeeded(value_sem_type);
       if (value_type == 0) {
@@ -3382,15 +3377,15 @@
     return 0;
   }
 
-  auto val_id = GenerateExpression(expr->expr());
+  auto val_id = GenerateExpression(expr->expr);
   if (val_id == 0) {
     return 0;
   }
-  val_id = GenerateLoadIfNeeded(TypeOf(expr->expr()), val_id);
+  val_id = GenerateLoadIfNeeded(TypeOf(expr->expr), val_id);
 
   // Bitcast does not allow same types, just emit a CopyObject
   auto* to_type = TypeOf(expr)->UnwrapRef();
-  auto* from_type = TypeOf(expr->expr())->UnwrapRef();
+  auto* from_type = TypeOf(expr->expr)->UnwrapRef();
   if (to_type->type_name() == from_type->type_name()) {
     if (!push_function_inst(
             spv::Op::OpCopyObject,
@@ -3465,17 +3460,17 @@
 
     auto* else_stmt = else_stmts[cur_else_idx];
     // Handle the else case by just outputting the statements.
-    if (!else_stmt->HasCondition()) {
-      if (!GenerateBlockStatement(else_stmt->body())) {
+    if (!else_stmt->condition) {
+      if (!GenerateBlockStatement(else_stmt->body)) {
         return false;
       }
     } else {
-      if (!GenerateConditionalBlock(else_stmt->condition(), else_stmt->body(),
+      if (!GenerateConditionalBlock(else_stmt->condition, else_stmt->body,
                                     cur_else_idx + 1, else_stmts)) {
         return false;
       }
     }
-    if (!LastIsTerminator(else_stmt->body())) {
+    if (!LastIsTerminator(else_stmt->body)) {
       if (!push_function_inst(spv::Op::OpBranch,
                               {Operand::Int(merge_block_id)})) {
         return false;
@@ -3503,25 +3498,25 @@
     //    if (cond) {} else {break;}
     //  }
     auto is_just_a_break = [](ast::BlockStatement* block) {
-      return block && (block->size() == 1) &&
-             block->last()->Is<ast::BreakStatement>();
+      return block && (block->statements.size() == 1) &&
+             block->Last()->Is<ast::BreakStatement>();
     };
-    if (is_just_a_break(stmt->body()) && !stmt->has_else_statements()) {
+    if (is_just_a_break(stmt->body) && stmt->else_statements.empty()) {
       // It's a break-if.
       TINT_ASSERT(Writer, !backedge_stack_.empty());
-      const auto cond_id = GenerateExpression(stmt->condition());
+      const auto cond_id = GenerateExpression(stmt->condition);
       backedge_stack_.back() =
           Backedge(spv::Op::OpBranchConditional,
                    {Operand::Int(cond_id), Operand::Int(ci.break_target_id),
                     Operand::Int(ci.loop_header_id)});
       return true;
-    } else if (stmt->body()->empty()) {
-      const auto& es = stmt->else_statements();
-      if (es.size() == 1 && !es.back()->HasCondition() &&
-          is_just_a_break(es.back()->body())) {
+    } else if (stmt->body->Empty()) {
+      const auto& es = stmt->else_statements;
+      if (es.size() == 1 && !es.back()->condition &&
+          is_just_a_break(es.back()->body)) {
         // It's a break-unless.
         TINT_ASSERT(Writer, !backedge_stack_.empty());
-        const auto cond_id = GenerateExpression(stmt->condition());
+        const auto cond_id = GenerateExpression(stmt->condition);
         backedge_stack_.back() =
             Backedge(spv::Op::OpBranchConditional,
                      {Operand::Int(cond_id), Operand::Int(ci.loop_header_id),
@@ -3531,8 +3526,8 @@
     }
   }
 
-  if (!GenerateConditionalBlock(stmt->condition(), stmt->body(), 0,
-                                stmt->else_statements())) {
+  if (!GenerateConditionalBlock(stmt->condition, stmt->body, 0,
+                                stmt->else_statements)) {
     return false;
   }
   return true;
@@ -3544,11 +3539,11 @@
 
   merge_stack_.push_back(merge_block_id);
 
-  auto cond_id = GenerateExpression(stmt->condition());
+  auto cond_id = GenerateExpression(stmt->condition);
   if (cond_id == 0) {
     return false;
   }
-  cond_id = GenerateLoadIfNeeded(TypeOf(stmt->condition()), cond_id);
+  cond_id = GenerateLoadIfNeeded(TypeOf(stmt->condition), cond_id);
 
   auto default_block = result_op();
   auto default_block_id = default_block.to_i();
@@ -3556,7 +3551,7 @@
   OperandList params = {Operand::Int(cond_id), Operand::Int(default_block_id)};
 
   std::vector<uint32_t> case_ids;
-  for (const auto* item : stmt->body()) {
+  for (const auto* item : stmt->body) {
     if (item->IsDefault()) {
       case_ids.push_back(default_block_id);
       continue;
@@ -3566,14 +3561,14 @@
     auto block_id = block.to_i();
 
     case_ids.push_back(block_id);
-    for (auto* selector : item->selectors()) {
+    for (auto* selector : item->selectors) {
       auto* int_literal = selector->As<ast::IntLiteral>();
       if (!int_literal) {
         error_ = "expected integer literal for switch case label";
         return false;
       }
 
-      params.push_back(Operand::Int(int_literal->value_as_u32()));
+      params.push_back(Operand::Int(int_literal->ValueAsU32()));
       params.push_back(Operand::Int(block_id));
     }
   }
@@ -3588,7 +3583,7 @@
   }
 
   bool generated_default = false;
-  auto& body = stmt->body();
+  auto& body = stmt->body;
   // We output the case statements in order they were entered in the original
   // source. Each fallthrough goes to the next case entry, so is a forward
   // branch, otherwise the branch is to the merge block which comes after
@@ -3603,11 +3598,11 @@
     if (!GenerateLabel(case_ids[i])) {
       return false;
     }
-    if (!GenerateBlockStatement(item->body())) {
+    if (!GenerateBlockStatement(item->body)) {
       return false;
     }
 
-    if (LastIsFallthrough(item->body())) {
+    if (LastIsFallthrough(item->body)) {
       if (i == (body.size() - 1)) {
         // This case is caught by Resolver validation
         TINT_UNREACHABLE(Writer, builder_.Diagnostics());
@@ -3617,7 +3612,7 @@
                               {Operand::Int(case_ids[i + 1])})) {
         return false;
       }
-    } else if (!LastIsTerminator(item->body())) {
+    } else if (!LastIsTerminator(item->body)) {
       if (!push_function_inst(spv::Op::OpBranch,
                               {Operand::Int(merge_block_id)})) {
         return false;
@@ -3641,12 +3636,12 @@
 }
 
 bool Builder::GenerateReturnStatement(ast::ReturnStatement* stmt) {
-  if (stmt->has_value()) {
-    auto val_id = GenerateExpression(stmt->value());
+  if (stmt->value) {
+    auto val_id = GenerateExpression(stmt->value);
     if (val_id == 0) {
       return false;
     }
-    val_id = GenerateLoadIfNeeded(TypeOf(stmt->value()), val_id);
+    val_id = GenerateLoadIfNeeded(TypeOf(stmt->value), val_id);
     if (!push_function_inst(spv::Op::OpReturnValue, {Operand::Int(val_id)})) {
       return false;
     }
@@ -3703,12 +3698,12 @@
   // manage scope outside of GenerateBlockStatement.
   scope_stack_.push_scope();
 
-  if (!GenerateBlockStatementWithoutScoping(stmt->body())) {
+  if (!GenerateBlockStatementWithoutScoping(stmt->body)) {
     return false;
   }
 
   // We only branch if the last element of the body didn't already branch.
-  if (!LastIsTerminator(stmt->body())) {
+  if (!LastIsTerminator(stmt->body)) {
     if (!push_function_inst(spv::Op::OpBranch,
                             {Operand::Int(continue_block_id)})) {
       return false;
@@ -3718,10 +3713,10 @@
   if (!GenerateLabel(continue_block_id)) {
     return false;
   }
-  if (stmt->has_continuing()) {
-    continuing_stack_.emplace_back(stmt->continuing()->last(), loop_header_id,
+  if (stmt->continuing && !stmt->continuing->Empty()) {
+    continuing_stack_.emplace_back(stmt->continuing->Last(), loop_header_id,
                                    merge_block_id);
-    if (!GenerateBlockStatementWithoutScoping(stmt->continuing())) {
+    if (!GenerateBlockStatementWithoutScoping(stmt->continuing)) {
       return false;
     }
     continuing_stack_.pop_back();
@@ -3754,7 +3749,7 @@
     return GenerateBreakStatement(b);
   }
   if (auto* c = stmt->As<ast::CallStatement>()) {
-    return GenerateCallExpression(c->expr()) != 0;
+    return GenerateCallExpression(c->expr) != 0;
   }
   if (auto* c = stmt->As<ast::ContinueStatement>()) {
     return GenerateContinueStatement(c);
@@ -3787,7 +3782,7 @@
 }
 
 bool Builder::GenerateVariableDeclStatement(ast::VariableDeclStatement* stmt) {
-  return GenerateFunctionVariable(stmt->variable());
+  return GenerateFunctionVariable(stmt->variable);
 }
 
 uint32_t Builder::GenerateTypeIfNeeded(const sem::Type* type) {
diff --git a/src/writer/spirv/builder_intrinsic_texture_test.cc b/src/writer/spirv/builder_intrinsic_texture_test.cc
index bb28957..a8f60c8 100644
--- a/src/writer/spirv/builder_intrinsic_texture_test.cc
+++ b/src/writer/spirv/builder_intrinsic_texture_test.cc
@@ -3169,8 +3169,8 @@
 TEST_P(IntrinsicTextureTest, Call) {
   auto param = GetParam();
 
-  auto* texture = param.buildTextureVariable(this);
-  auto* sampler = param.buildSamplerVariable(this);
+  auto* texture = param.BuildTextureVariable(this);
+  auto* sampler = param.BuildSamplerVariable(this);
 
   auto* call = Call(param.function, param.args(this));
   auto* stmt = ast::intrinsic::test::ReturnsVoid(param.overload)
@@ -3197,8 +3197,8 @@
 TEST_P(IntrinsicTextureTest, ValidateSPIRV) {
   auto param = GetParam();
 
-  param.buildTextureVariable(this);
-  param.buildSamplerVariable(this);
+  param.BuildTextureVariable(this);
+  param.BuildSamplerVariable(this);
 
   auto* call = Call(param.function, param.args(this));
 
@@ -3220,8 +3220,8 @@
   // The point of this test is to try to generate the texture
   // intrinsic call outside a function.
 
-  auto* texture = param.buildTextureVariable(this);
-  auto* sampler = param.buildSamplerVariable(this);
+  auto* texture = param.BuildTextureVariable(this);
+  auto* sampler = param.BuildSamplerVariable(this);
 
   auto* call = Call(param.function, param.args(this));
   auto* stmt = ast::intrinsic::test::ReturnsVoid(param.overload)
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index c226b1f..68133bb 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -96,8 +96,8 @@
 bool GeneratorImpl::EmitTypeDecl(const ast::TypeDecl* ty) {
   if (auto* alias = ty->As<ast::Alias>()) {
     auto out = line();
-    out << "type " << program_->Symbols().NameFor(alias->symbol()) << " = ";
-    if (!EmitType(out, alias->type())) {
+    out << "type " << program_->Symbols().NameFor(alias->name) << " = ";
+    if (!EmitType(out, alias->type)) {
       return false;
     }
     out << ";";
@@ -147,14 +147,14 @@
 bool GeneratorImpl::EmitArrayAccessor(std::ostream& out,
                                       ast::ArrayAccessorExpression* expr) {
   bool paren_lhs =
-      !expr->array()
+      !expr->array
            ->IsAnyOf<ast::ArrayAccessorExpression, ast::CallExpression,
                      ast::IdentifierExpression, ast::MemberAccessorExpression,
                      ast::TypeConstructorExpression>();
   if (paren_lhs) {
     out << "(";
   }
-  if (!EmitExpression(out, expr->array())) {
+  if (!EmitExpression(out, expr->array)) {
     return false;
   }
   if (paren_lhs) {
@@ -162,7 +162,7 @@
   }
   out << "[";
 
-  if (!EmitExpression(out, expr->idx_expr())) {
+  if (!EmitExpression(out, expr->index)) {
     return false;
   }
   out << "]";
@@ -173,14 +173,14 @@
 bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
                                        ast::MemberAccessorExpression* expr) {
   bool paren_lhs =
-      !expr->structure()
+      !expr->structure
            ->IsAnyOf<ast::ArrayAccessorExpression, ast::CallExpression,
                      ast::IdentifierExpression, ast::MemberAccessorExpression,
                      ast::TypeConstructorExpression>();
   if (paren_lhs) {
     out << "(";
   }
-  if (!EmitExpression(out, expr->structure())) {
+  if (!EmitExpression(out, expr->structure)) {
     return false;
   }
   if (paren_lhs) {
@@ -189,18 +189,18 @@
 
   out << ".";
 
-  return EmitExpression(out, expr->member());
+  return EmitExpression(out, expr->member);
 }
 
 bool GeneratorImpl::EmitBitcast(std::ostream& out,
                                 ast::BitcastExpression* expr) {
   out << "bitcast<";
-  if (!EmitType(out, expr->type())) {
+  if (!EmitType(out, expr->type)) {
     return false;
   }
 
   out << ">(";
-  if (!EmitExpression(out, expr->expr())) {
+  if (!EmitExpression(out, expr->expr)) {
     return false;
   }
 
@@ -209,13 +209,13 @@
 }
 
 bool GeneratorImpl::EmitCall(std::ostream& out, ast::CallExpression* expr) {
-  if (!EmitExpression(out, expr->func())) {
+  if (!EmitExpression(out, expr->func)) {
     return false;
   }
   out << "(";
 
   bool first = true;
-  const auto& args = expr->args();
+  const auto& args = expr->args;
   for (auto* arg : args) {
     if (!first) {
       out << ", ";
@@ -242,14 +242,14 @@
 
 bool GeneratorImpl::EmitTypeConstructor(std::ostream& out,
                                         ast::TypeConstructorExpression* expr) {
-  if (!EmitType(out, expr->type())) {
+  if (!EmitType(out, expr->type)) {
     return false;
   }
 
   out << "(";
 
   bool first = true;
-  for (auto* e : expr->values()) {
+  for (auto* e : expr->values) {
     if (!first) {
       out << ", ";
     }
@@ -267,18 +267,18 @@
 bool GeneratorImpl::EmitScalarConstructor(
     std::ostream& out,
     ast::ScalarConstructorExpression* expr) {
-  return EmitLiteral(out, expr->literal());
+  return EmitLiteral(out, expr->literal);
 }
 
 bool GeneratorImpl::EmitLiteral(std::ostream& out, ast::Literal* lit) {
   if (auto* bl = lit->As<ast::BoolLiteral>()) {
-    out << (bl->IsTrue() ? "true" : "false");
+    out << (bl->value ? "true" : "false");
   } else if (auto* fl = lit->As<ast::FloatLiteral>()) {
-    out << FloatToBitPreservingString(fl->value());
+    out << FloatToBitPreservingString(fl->value);
   } else if (auto* sl = lit->As<ast::SintLiteral>()) {
-    out << sl->value();
+    out << sl->value;
   } else if (auto* ul = lit->As<ast::UintLiteral>()) {
-    out << ul->value() << "u";
+    out << ul->value << "u";
   } else {
     diagnostics_.add_error(diag::System::Writer, "unknown literal type");
     return false;
@@ -288,66 +288,66 @@
 
 bool GeneratorImpl::EmitIdentifier(std::ostream& out,
                                    ast::IdentifierExpression* expr) {
-  out << program_->Symbols().NameFor(expr->symbol());
+  out << program_->Symbols().NameFor(expr->symbol);
   return true;
 }
 
 bool GeneratorImpl::EmitFunction(ast::Function* func) {
-  if (func->decorations().size()) {
-    if (!EmitDecorations(line(), func->decorations())) {
+  if (func->decorations.size()) {
+    if (!EmitDecorations(line(), func->decorations)) {
       return false;
     }
   }
   {
     auto out = line();
-    out << "fn " << program_->Symbols().NameFor(func->symbol()) << "(";
+    out << "fn " << program_->Symbols().NameFor(func->symbol) << "(";
 
     bool first = true;
-    for (auto* v : func->params()) {
+    for (auto* v : func->params) {
       if (!first) {
         out << ", ";
       }
       first = false;
 
-      if (!v->decorations().empty()) {
-        if (!EmitDecorations(out, v->decorations())) {
+      if (!v->decorations.empty()) {
+        if (!EmitDecorations(out, v->decorations)) {
           return false;
         }
         out << " ";
       }
 
-      out << program_->Symbols().NameFor(v->symbol()) << " : ";
+      out << program_->Symbols().NameFor(v->symbol) << " : ";
 
-      if (!EmitType(out, v->type())) {
+      if (!EmitType(out, v->type)) {
         return false;
       }
     }
 
     out << ")";
 
-    if (!func->return_type()->Is<ast::Void>() ||
-        !func->return_type_decorations().empty()) {
+    if (!func->return_type->Is<ast::Void>() ||
+        !func->return_type_decorations.empty()) {
       out << " -> ";
 
-      if (!func->return_type_decorations().empty()) {
-        if (!EmitDecorations(out, func->return_type_decorations())) {
+      if (!func->return_type_decorations.empty()) {
+        if (!EmitDecorations(out, func->return_type_decorations)) {
           return false;
         }
         out << " ";
       }
 
-      if (!EmitType(out, func->return_type())) {
+      if (!EmitType(out, func->return_type)) {
         return false;
       }
     }
 
-    if (func->body()) {
+    if (func->body) {
       out << " {";
     }
   }
 
-  if (func->body()) {
-    if (!EmitStatementsWithIndent(func->body()->statements())) {
+  if (func->body) {
+    if (!EmitStatementsWithIndent(func->body->statements)) {
       return false;
     }
     line() << "}";
@@ -388,20 +388,20 @@
 
 bool GeneratorImpl::EmitType(std::ostream& out, const ast::Type* ty) {
   if (auto* ary = ty->As<ast::Array>()) {
-    for (auto* deco : ary->decorations()) {
+    for (auto* deco : ary->decorations) {
       if (auto* stride = deco->As<ast::StrideDecoration>()) {
-        out << "[[stride(" << stride->stride() << ")]] ";
+        out << "[[stride(" << stride->stride << ")]] ";
       }
     }
 
     out << "array<";
-    if (!EmitType(out, ary->type())) {
+    if (!EmitType(out, ary->type)) {
       return false;
     }
 
     if (!ary->IsRuntimeArray()) {
       out << ", ";
-      if (!EmitExpression(out, ary->Size())) {
+      if (!EmitExpression(out, ary->count)) {
         return false;
       }
     }
@@ -414,26 +414,26 @@
   } else if (ty->Is<ast::I32>()) {
     out << "i32";
   } else if (auto* mat = ty->As<ast::Matrix>()) {
-    out << "mat" << mat->columns() << "x" << mat->rows() << "<";
-    if (!EmitType(out, mat->type())) {
+    out << "mat" << mat->columns << "x" << mat->rows << "<";
+    if (!EmitType(out, mat->type)) {
       return false;
     }
     out << ">";
   } else if (auto* ptr = ty->As<ast::Pointer>()) {
-    out << "ptr<" << ptr->storage_class() << ", ";
-    if (!EmitType(out, ptr->type())) {
+    out << "ptr<" << ptr->storage_class << ", ";
+    if (!EmitType(out, ptr->type)) {
       return false;
     }
-    if (ptr->access() != ast::Access::kUndefined) {
+    if (ptr->access != ast::Access::kUndefined) {
       out << ", ";
-      if (!EmitAccess(out, ptr->access())) {
+      if (!EmitAccess(out, ptr->access)) {
         return false;
       }
     }
     out << ">";
   } else if (auto* atomic = ty->As<ast::Atomic>()) {
     out << "atomic<";
-    if (!EmitType(out, atomic->type())) {
+    if (!EmitType(out, atomic->type)) {
       return false;
     }
     out << ">";
@@ -462,7 +462,7 @@
       return false;
     }
 
-    switch (texture->dim()) {
+    switch (texture->dim) {
       case ast::TextureDimension::k1d:
         out << "1d";
         break;
@@ -489,23 +489,23 @@
 
     if (auto* sampled = texture->As<ast::SampledTexture>()) {
       out << "<";
-      if (!EmitType(out, sampled->type())) {
+      if (!EmitType(out, sampled->type)) {
         return false;
       }
       out << ">";
     } else if (auto* ms = texture->As<ast::MultisampledTexture>()) {
       out << "<";
-      if (!EmitType(out, ms->type())) {
+      if (!EmitType(out, ms->type)) {
         return false;
       }
       out << ">";
     } else if (auto* storage = texture->As<ast::StorageTexture>()) {
       out << "<";
-      if (!EmitImageFormat(out, storage->image_format())) {
+      if (!EmitImageFormat(out, storage->format)) {
         return false;
       }
       out << ", ";
-      if (!EmitAccess(out, storage->access())) {
+      if (!EmitAccess(out, storage->access)) {
         return false;
       }
       out << ">";
@@ -514,15 +514,15 @@
   } else if (ty->Is<ast::U32>()) {
     out << "u32";
   } else if (auto* vec = ty->As<ast::Vector>()) {
-    out << "vec" << vec->size() << "<";
-    if (!EmitType(out, vec->type())) {
+    out << "vec" << vec->width << "<";
+    if (!EmitType(out, vec->type)) {
       return false;
     }
     out << ">";
   } else if (ty->Is<ast::Void>()) {
     out << "void";
   } else if (auto* tn = ty->As<ast::TypeName>()) {
-    out << program_->Symbols().NameFor(tn->name());
+    out << program_->Symbols().NameFor(tn->name);
   } else {
     diagnostics_.add_error(
         diag::System::Writer,
@@ -533,12 +533,12 @@
 }
 
 bool GeneratorImpl::EmitStructType(const ast::Struct* str) {
-  if (str->decorations().size()) {
-    if (!EmitDecorations(line(), str->decorations())) {
+  if (str->decorations.size()) {
+    if (!EmitDecorations(line(), str->decorations)) {
       return false;
     }
   }
-  line() << "struct " << program_->Symbols().NameFor(str->name()) << " {";
+  line() << "struct " << program_->Symbols().NameFor(str->name) << " {";
 
   auto add_padding = [&](uint32_t size) {
     line() << "[[size(" << size << ")]]";
@@ -550,7 +550,7 @@
 
   increment_indent();
   uint32_t offset = 0;
-  for (auto* mem : str->members()) {
+  for (auto* mem : str->members) {
     // TODO(crbug.com/tint/798) move the [[offset]] decoration handling to the
     // transform::Wgsl sanitizer.
     if (auto* mem_sem = program_->Sem().Get(mem)) {
@@ -566,8 +566,8 @@
     // by the SPIR-V reader and are consumed by the Resolver(). These should not
     // be emitted, but instead struct padding fields should be emitted.
     ast::DecorationList decorations_sanitized;
-    decorations_sanitized.reserve(mem->decorations().size());
-    for (auto* deco : mem->decorations()) {
+    decorations_sanitized.reserve(mem->decorations.size());
+    for (auto* deco : mem->decorations) {
       if (!deco->Is<ast::StructMemberOffsetDecoration>()) {
         decorations_sanitized.emplace_back(deco);
       }
@@ -580,8 +580,8 @@
     }
 
     auto out = line();
-    out << program_->Symbols().NameFor(mem->symbol()) << " : ";
-    if (!EmitType(out, mem->type())) {
+    out << program_->Symbols().NameFor(mem->symbol) << " : ";
+    if (!EmitType(out, mem->type)) {
       return false;
     }
     out << ";";
@@ -593,19 +593,19 @@
 }
 
 bool GeneratorImpl::EmitVariable(std::ostream& out, ast::Variable* var) {
-  if (!var->decorations().empty()) {
-    if (!EmitDecorations(out, var->decorations())) {
+  if (!var->decorations.empty()) {
+    if (!EmitDecorations(out, var->decorations)) {
       return false;
     }
     out << " ";
   }
 
-  if (var->is_const()) {
+  if (var->is_const) {
     out << "let";
   } else {
     out << "var";
-    auto sc = var->declared_storage_class();
-    auto ac = var->declared_access();
+    auto sc = var->declared_storage_class;
+    auto ac = var->declared_access;
     if (sc != ast::StorageClass::kNone || ac != ast::Access::kUndefined) {
       out << "<" << sc;
       if (ac != ast::Access::kUndefined) {
@@ -618,18 +618,18 @@
     }
   }
 
-  out << " " << program_->Symbols().NameFor(var->symbol());
+  out << " " << program_->Symbols().NameFor(var->symbol);
 
-  if (auto* ty = var->type()) {
+  if (auto* ty = var->type) {
     out << " : ";
     if (!EmitType(out, ty)) {
       return false;
     }
   }
 
-  if (var->constructor() != nullptr) {
+  if (var->constructor != nullptr) {
     out << " = ";
-    if (!EmitExpression(out, var->constructor())) {
+    if (!EmitExpression(out, var->constructor)) {
       return false;
     }
   }
@@ -649,7 +649,7 @@
     first = false;
 
     if (auto* workgroup = deco->As<ast::WorkgroupDecoration>()) {
-      auto values = workgroup->values();
+      auto values = workgroup->Values();
       out << "workgroup_size(";
       for (int i = 0; i < 3; i++) {
         if (values[i]) {
@@ -665,34 +665,34 @@
     } else if (deco->Is<ast::StructBlockDecoration>()) {
       out << "block";
     } else if (auto* stage = deco->As<ast::StageDecoration>()) {
-      out << "stage(" << stage->value() << ")";
+      out << "stage(" << stage->stage << ")";
     } else if (auto* binding = deco->As<ast::BindingDecoration>()) {
-      out << "binding(" << binding->value() << ")";
+      out << "binding(" << binding->value << ")";
     } else if (auto* group = deco->As<ast::GroupDecoration>()) {
-      out << "group(" << group->value() << ")";
+      out << "group(" << group->value << ")";
     } else if (auto* location = deco->As<ast::LocationDecoration>()) {
-      out << "location(" << location->value() << ")";
+      out << "location(" << location->value << ")";
     } else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
-      out << "builtin(" << builtin->value() << ")";
+      out << "builtin(" << builtin->builtin << ")";
     } else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) {
-      out << "interpolate(" << interpolate->type();
-      if (interpolate->sampling() != ast::InterpolationSampling::kNone) {
-        out << ", " << interpolate->sampling();
+      out << "interpolate(" << interpolate->type;
+      if (interpolate->sampling != ast::InterpolationSampling::kNone) {
+        out << ", " << interpolate->sampling;
       }
       out << ")";
     } else if (deco->Is<ast::InvariantDecoration>()) {
       out << "invariant";
     } else if (auto* override_deco = deco->As<ast::OverrideDecoration>()) {
       out << "override";
-      if (override_deco->HasValue()) {
-        out << "(" << override_deco->value() << ")";
+      if (override_deco->has_value) {
+        out << "(" << override_deco->value << ")";
       }
     } else if (auto* size = deco->As<ast::StructMemberSizeDecoration>()) {
-      out << "size(" << size->size() << ")";
+      out << "size(" << size->size << ")";
     } else if (auto* align = deco->As<ast::StructMemberAlignDecoration>()) {
-      out << "align(" << align->align() << ")";
+      out << "align(" << align->align << ")";
     } else if (auto* stride = deco->As<ast::StrideDecoration>()) {
-      out << "stride(" << stride->stride() << ")";
+      out << "stride(" << stride->stride << ")";
     } else if (auto* internal = deco->As<ast::InternalDecoration>()) {
       out << "internal(" << internal->InternalName() << ")";
     } else {
@@ -709,12 +709,12 @@
 bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) {
   out << "(";
 
-  if (!EmitExpression(out, expr->lhs())) {
+  if (!EmitExpression(out, expr->lhs)) {
     return false;
   }
   out << " ";
 
-  switch (expr->op()) {
+  switch (expr->op) {
     case ast::BinaryOp::kAnd:
       out << "&";
       break;
@@ -776,7 +776,7 @@
   }
   out << " ";
 
-  if (!EmitExpression(out, expr->rhs())) {
+  if (!EmitExpression(out, expr->rhs)) {
     return false;
   }
 
@@ -786,7 +786,7 @@
 
 bool GeneratorImpl::EmitUnaryOp(std::ostream& out,
                                 ast::UnaryOpExpression* expr) {
-  switch (expr->op()) {
+  switch (expr->op) {
     case ast::UnaryOp::kAddressOf:
       out << "&";
       break;
@@ -805,7 +805,7 @@
   }
   out << "(";
 
-  if (!EmitExpression(out, expr->expr())) {
+  if (!EmitExpression(out, expr->expr)) {
     return false;
   }
 
@@ -816,7 +816,7 @@
 
 bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
   line() << "{";
-  if (!EmitStatementsWithIndent(stmt->statements())) {
+  if (!EmitStatementsWithIndent(stmt->statements)) {
     return false;
   }
   line() << "}";
@@ -836,7 +836,7 @@
   }
   if (auto* c = stmt->As<ast::CallStatement>()) {
     auto out = line();
-    if (!EmitCall(out, c->expr())) {
+    if (!EmitCall(out, c->expr)) {
       return false;
     }
     out << ";";
@@ -867,7 +867,7 @@
     return EmitSwitch(s);
   }
   if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
-    return EmitVariable(line(), v->variable());
+    return EmitVariable(line(), v->variable);
   }
 
   diagnostics_.add_error(
@@ -893,13 +893,13 @@
 bool GeneratorImpl::EmitAssign(ast::AssignmentStatement* stmt) {
   auto out = line();
 
-  if (!EmitExpression(out, stmt->lhs())) {
+  if (!EmitExpression(out, stmt->lhs)) {
     return false;
   }
 
   out << " = ";
 
-  if (!EmitExpression(out, stmt->rhs())) {
+  if (!EmitExpression(out, stmt->rhs)) {
     return false;
   }
 
@@ -921,7 +921,7 @@
     out << "case ";
 
     bool first = true;
-    for (auto* selector : stmt->selectors()) {
+    for (auto* selector : stmt->selectors) {
       if (!first) {
         out << ", ";
       }
@@ -934,7 +934,7 @@
     out << ": {";
   }
 
-  if (!EmitStatementsWithIndent(stmt->body()->statements())) {
+  if (!EmitStatementsWithIndent(stmt->body->statements)) {
     return false;
   }
 
@@ -956,21 +956,21 @@
   {
     auto out = line();
     out << "if (";
-    if (!EmitExpression(out, stmt->condition())) {
+    if (!EmitExpression(out, stmt->condition)) {
       return false;
     }
     out << ") {";
   }
 
-  if (!EmitStatementsWithIndent(stmt->body()->statements())) {
+  if (!EmitStatementsWithIndent(stmt->body->statements)) {
     return false;
   }
 
-  for (auto* e : stmt->else_statements()) {
-    if (e->HasCondition()) {
+  for (auto* e : stmt->else_statements) {
+    if (e->condition) {
       auto out = line();
       out << "} elseif (";
-      if (!EmitExpression(out, e->condition())) {
+      if (!EmitExpression(out, e->condition)) {
         return false;
       }
       out << ") {";
@@ -978,7 +978,7 @@
       line() << "} else {";
     }
 
-    if (!EmitStatementsWithIndent(e->body()->statements())) {
+    if (!EmitStatementsWithIndent(e->body->statements)) {
       return false;
     }
   }
@@ -997,14 +997,14 @@
   line() << "loop {";
   increment_indent();
 
-  if (!EmitStatements(stmt->body()->statements())) {
+  if (!EmitStatements(stmt->body->statements)) {
     return false;
   }
 
-  if (stmt->has_continuing()) {
+  if (stmt->continuing && !stmt->continuing->Empty()) {
     line();
     line() << "continuing {";
-    if (!EmitStatementsWithIndent(stmt->continuing()->statements())) {
+    if (!EmitStatementsWithIndent(stmt->continuing->statements)) {
       return false;
     }
     line() << "}";
@@ -1018,7 +1018,7 @@
 
 bool GeneratorImpl::EmitForLoop(ast::ForLoopStatement* stmt) {
   TextBuffer init_buf;
-  if (auto* init = stmt->initializer()) {
+  if (auto* init = stmt->initializer) {
     TINT_SCOPED_ASSIGNMENT(current_buffer_, &init_buf);
     if (!EmitStatement(init)) {
       return false;
@@ -1026,7 +1026,7 @@
   }
 
   TextBuffer cont_buf;
-  if (auto* cont = stmt->continuing()) {
+  if (auto* cont = stmt->continuing) {
     TINT_SCOPED_ASSIGNMENT(current_buffer_, &cont_buf);
     if (!EmitStatement(cont)) {
       return false;
@@ -1055,7 +1055,7 @@
 
       out << "; ";
 
-      if (auto* cond = stmt->condition()) {
+      if (auto* cond = stmt->condition) {
         if (!EmitExpression(out, cond)) {
           return false;
         }
@@ -1081,7 +1081,7 @@
     out << " {";
   }
 
-  if (!EmitStatementsWithIndent(stmt->body()->statements())) {
+  if (!EmitStatementsWithIndent(stmt->body->statements)) {
     return false;
   }
 
@@ -1093,9 +1093,9 @@
 bool GeneratorImpl::EmitReturn(ast::ReturnStatement* stmt) {
   auto out = line();
   out << "return";
-  if (stmt->has_value()) {
+  if (stmt->value) {
     out << " ";
-    if (!EmitExpression(out, stmt->value())) {
+    if (!EmitExpression(out, stmt->value)) {
       return false;
     }
   }
@@ -1107,7 +1107,7 @@
   {
     auto out = line();
     out << "switch(";
-    if (!EmitExpression(out, stmt->condition())) {
+    if (!EmitExpression(out, stmt->condition)) {
       return false;
     }
     out << ") {";
@@ -1115,7 +1115,7 @@
 
   {
     ScopedIndent si(this);
-    for (auto* s : stmt->body()) {
+    for (auto* s : stmt->body) {
       if (!EmitCase(s)) {
         return false;
       }
diff --git a/src/writer/wgsl/generator_impl_case_test.cc b/src/writer/wgsl/generator_impl_case_test.cc
index e03ee56..92b20db 100644
--- a/src/writer/wgsl/generator_impl_case_test.cc
+++ b/src/writer/wgsl/generator_impl_case_test.cc
@@ -30,7 +30,7 @@
 
   gen.increment_indent();
 
-  ASSERT_TRUE(gen.EmitCase(s->body()[0])) << gen.error();
+  ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.error();
   EXPECT_EQ(gen.result(), R"(  case 5: {
     break;
   }
@@ -47,7 +47,7 @@
 
   gen.increment_indent();
 
-  ASSERT_TRUE(gen.EmitCase(s->body()[0])) << gen.error();
+  ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.error();
   EXPECT_EQ(gen.result(), R"(  case 5, 6: {
     break;
   }
@@ -62,7 +62,7 @@
 
   gen.increment_indent();
 
-  ASSERT_TRUE(gen.EmitCase(s->body()[0])) << gen.error();
+  ASSERT_TRUE(gen.EmitCase(s->body[0])) << gen.error();
   EXPECT_EQ(gen.result(), R"(  default: {
     break;
   }