Merge pull request #130 from EricRahm/use_string_template

Switch `code_templates` to `string.Template`
diff --git a/compiler/back_end/cpp/generated_code_templates b/compiler/back_end/cpp/generated_code_templates
index 4554b39..2854233 100644
--- a/compiler/back_end/cpp/generated_code_templates
+++ b/compiler/back_end/cpp/generated_code_templates
@@ -21,10 +21,12 @@
 // prefixed with `emboss_reserved_local_` to avoid conflicting with struct field
 // names.
 
+// clang-format off
+
 // ** outline ** ///////////////////////////////////////////////////////////////
 // Generated by the Emboss compiler.  DO NOT EDIT!
-#ifndef $_header_guard_$
-#define $_header_guard_$
+#ifndef ${header_guard}
+#define ${header_guard}
 #include <stdint.h>
 #include <string.h>
 
@@ -35,117 +37,117 @@
 
 #include "runtime/cpp/emboss_cpp_util.h"
 
-$_includes_$
+${includes}
 
 // NOLINTBEGIN
-$_body_$
+${body}
 // NOLINTEND
 
-#endif  // $_header_guard_$
+#endif  // ${header_guard}
 
 
 // ** include ** ///////////////////////////////////////////////////////////////
-#include "$_file_name_$"
+#include "${file_name}"
 
 
 // ** body ** //////////////////////////////////////////////////////////////////
-$_type_declarations_$
-$_type_definitions_$
-$_method_definitions_$
+${type_declarations}
+${type_definitions}
+${method_definitions}
 
 
 // ** namespace_wrap ** ////////////////////////////////////////////////////////
-namespace $_component_$ {
-$_body_$
-}  // namespace $_component_$
+namespace ${component} {
+${body}
+}  // namespace ${component}
 
 
 // ** structure_view_declaration ** ////////////////////////////////////////////
 template <class Storage>
-class Generic$_name_$View;
+class Generic${name}View;
 
 
 // ** structure_view_class ** //////////////////////////////////////////////////
 template <class View>
-struct EmbossReservedInternalIsGeneric$_name_$View;
+struct EmbossReservedInternalIsGeneric${name}View;
 
 template <class Storage>
-class Generic$_name_$View final {
+class Generic${name}View final {
  public:
-  Generic$_name_$View() : backing_() {}
-  explicit Generic$_name_$View(
-      $_constructor_parameters_$ Storage emboss_reserved_local_bytes)
-      : backing_(emboss_reserved_local_bytes) $_parameter_initializers_$
-        $_initialize_parameters_initialized_true_$ {}
+  Generic${name}View() : backing_() {}
+  explicit Generic${name}View(
+      ${constructor_parameters} Storage emboss_reserved_local_bytes)
+      : backing_(emboss_reserved_local_bytes) ${parameter_initializers}
+        ${initialize_parameters_initialized_true} {}
 
   // Views over compatible backing storage should be freely assignable.
   template <typename OtherStorage>
-  Generic$_name_$View(
-      const Generic$_name_$View<OtherStorage> &emboss_reserved_local_other)
+  Generic${name}View(
+      const Generic${name}View<OtherStorage> &emboss_reserved_local_other)
       : backing_{emboss_reserved_local_other.BackingStorage()}
-        $_parameter_copy_initializers_$ {}
+        ${parameter_copy_initializers} {}
 
   // Allow pass-through construction of backing_, but only if there is at least
   // one argument, and, if exactly one argument, that argument is not a
-  // (possibly c/v/ref-qualified) Generic$_name_$View.
+  // (possibly c/v/ref-qualified) Generic${name}View.
   //
   // Explicitly ruling out overloads that might match the copy or move
   // constructor is necessary in order for the copy and move constructors to be
   // reliably found during overload resolution.
   template <typename Arg,
             typename = typename ::std::enable_if<
-                !EmbossReservedInternalIsGeneric$_name_$View<
+                !EmbossReservedInternalIsGeneric${name}View<
                     typename ::std::remove_cv<typename ::std::remove_reference<
                         Arg>::type>::type>::value>::type>
-  explicit Generic$_name_$View(
-      $_constructor_parameters_$ Arg &&emboss_reserved_local_arg)
+  explicit Generic${name}View(
+      ${constructor_parameters} Arg &&emboss_reserved_local_arg)
       : backing_(::std::forward<Arg>(
-            emboss_reserved_local_arg)) $_parameter_initializers_$
-        $_initialize_parameters_initialized_true_$ {}
+            emboss_reserved_local_arg)) ${parameter_initializers}
+        ${initialize_parameters_initialized_true} {}
   template <typename Arg0, typename Arg1, typename... Args>
-  explicit Generic$_name_$View(
-      $_constructor_parameters_$ Arg0 &&emboss_reserved_local_arg0,
+  explicit Generic${name}View(
+      ${constructor_parameters} Arg0 &&emboss_reserved_local_arg0,
       Arg1 &&emboss_reserved_local_arg1, Args &&... emboss_reserved_local_args)
       : backing_(::std::forward<Arg0>(emboss_reserved_local_arg0),
                  ::std::forward<Arg1>(emboss_reserved_local_arg1),
                  ::std::forward<Args>(
-                     emboss_reserved_local_args)...) $_parameter_initializers_$
-        $_initialize_parameters_initialized_true_$ {}
+                     emboss_reserved_local_args)...) ${parameter_initializers}
+        ${initialize_parameters_initialized_true} {}
 
   template <typename OtherStorage>
-  Generic$_name_$View<Storage> &operator=(
-      const Generic$_name_$View<OtherStorage> &emboss_reserved_local_other) {
+  Generic${name}View<Storage> &operator=(
+      const Generic${name}View<OtherStorage> &emboss_reserved_local_other) {
     backing_ = emboss_reserved_local_other.BackingStorage();
     return *this;
   }
 
-  $_enum_usings_$
+  ${enum_usings}
 
   bool Ok() const {
     if (!IsComplete()) return false;
-$_parameter_ok_checks_$
-$_field_ok_checks_$
-$_requires_check_$
+${parameter_ok_checks}
+${field_ok_checks}
+${requires_check}
     return true;
   }
   Storage BackingStorage() const { return backing_; }
   bool IsComplete() const {
-    return backing_.Ok() && IntrinsicSizeIn$_units_$().Ok() &&
-           backing_.SizeIn$_units_$() >=
+    return backing_.Ok() && IntrinsicSizeIn${units}().Ok() &&
+           backing_.SizeIn${units}() >=
                static_cast</**/ ::std::size_t>(
-                   IntrinsicSizeIn$_units_$().UncheckedRead());
+                   IntrinsicSizeIn${units}().UncheckedRead());
   }
-$_size_method_$
+${size_method}
 
   template <typename OtherStorage>
   bool Equals(
-      Generic$_name_$View<OtherStorage> emboss_reserved_local_other) const {
-    $_equals_method_body_$ return true;
+      Generic${name}View<OtherStorage> emboss_reserved_local_other) const {
+    ${equals_method_body} return true;
   }
   template <typename OtherStorage>
   bool UncheckedEquals(
-      Generic$_name_$View<OtherStorage> emboss_reserved_local_other) const {
-    $_unchecked_equals_method_body_$ return true;
+      Generic${name}View<OtherStorage> emboss_reserved_local_other) const {
+    ${unchecked_equals_method_body} return true;
   }
   // (Unchecked)CopyFrom copies the number of bytes included in the other view,
   // and ignores the size of the current view.  Even if they differ before
@@ -154,25 +156,25 @@
   // destination view's size should be updated by the copy.
   template <typename OtherStorage>
   void UncheckedCopyFrom(
-      Generic$_name_$View<OtherStorage> emboss_reserved_local_other) const {
+      Generic${name}View<OtherStorage> emboss_reserved_local_other) const {
     backing_.UncheckedCopyFrom(
         emboss_reserved_local_other.BackingStorage(),
-        emboss_reserved_local_other.IntrinsicSizeIn$_units_$().UncheckedRead());
+        emboss_reserved_local_other.IntrinsicSizeIn${units}().UncheckedRead());
   }
 
   template <typename OtherStorage>
   void CopyFrom(
-      Generic$_name_$View<OtherStorage> emboss_reserved_local_other) const {
+      Generic${name}View<OtherStorage> emboss_reserved_local_other) const {
     backing_.CopyFrom(
         emboss_reserved_local_other.BackingStorage(),
-        emboss_reserved_local_other.IntrinsicSizeIn$_units_$().Read());
+        emboss_reserved_local_other.IntrinsicSizeIn${units}().Read());
   }
   template <typename OtherStorage>
   bool TryToCopyFrom(
-      Generic$_name_$View<OtherStorage> emboss_reserved_local_other) const {
+      Generic${name}View<OtherStorage> emboss_reserved_local_other) const {
       return emboss_reserved_local_other.Ok() && backing_.TryToCopyFrom(
         emboss_reserved_local_other.BackingStorage(),
-        emboss_reserved_local_other.IntrinsicSizeIn$_units_$().Read());
+        emboss_reserved_local_other.IntrinsicSizeIn${units}().Read());
   }
 
   template <class Stream>
@@ -197,7 +199,7 @@
                                         &emboss_reserved_local_colon))
         return false;
       if (emboss_reserved_local_colon != ":") return false;
-$_decode_fields_$
+${decode_fields}
       // decode_fields will `continue` if it successfully finds a field.
       return false;
     }
@@ -215,7 +217,7 @@
       emboss_reserved_local_stream->Write("{");
     }
     bool emboss_reserved_local_wrote_field = false;
-$_write_fields_$
+${write_fields}
     // Avoid unused variable warnings for empty structures:
     (void)emboss_reserved_local_wrote_field;
     if (emboss_reserved_local_options.multiline()) {
@@ -229,12 +231,12 @@
 
   static constexpr bool IsAggregate() { return true; }
 
-$_field_method_declarations_$
+${field_method_declarations}
 
  private:
   Storage backing_;
-  $_parameter_fields_$
-  $_parameters_initialized_flag_$
+  ${parameter_fields}
+  ${parameters_initialized_flag}
 
   // This is a bit of a hack to handle Equals() and UncheckedEquals() between
   // views with different underlying storage -- otherwise, structs with
@@ -243,66 +245,66 @@
   // TODO(bolms): Revisit this once the special-case code for anonymous members
   // is replaced by explicit read/write virtual fields in the IR.
   template <class OtherStorage>
-  friend class Generic$_name_$View;
+  friend class Generic${name}View;
 };
-using $_name_$View =
-    Generic$_name_$View</**/ ::emboss::support::ReadOnlyContiguousBuffer>;
-using $_name_$Writer =
-    Generic$_name_$View</**/ ::emboss::support::ReadWriteContiguousBuffer>;
+using ${name}View =
+    Generic${name}View</**/ ::emboss::support::ReadOnlyContiguousBuffer>;
+using ${name}Writer =
+    Generic${name}View</**/ ::emboss::support::ReadWriteContiguousBuffer>;
 
 template <class View>
-struct EmbossReservedInternalIsGeneric$_name_$View {
+struct EmbossReservedInternalIsGeneric${name}View {
   static constexpr const bool value = false;
 };
 
 template <class Storage>
-struct EmbossReservedInternalIsGeneric$_name_$View<
-    Generic$_name_$View<Storage>> {
+struct EmbossReservedInternalIsGeneric${name}View<
+    Generic${name}View<Storage>> {
   static constexpr const bool value = true;
 };
 
 template <typename T>
-inline Generic$_name_$View<
+inline Generic${name}View<
     /**/ ::emboss::support::ContiguousBuffer<
         typename ::std::remove_reference<
             decltype(*::std::declval<T>()->data())>::type,
         1, 0>>
-Make$_name_$View($_constructor_parameters_$ T &&emboss_reserved_local_arg) {
-  return Generic$_name_$View<
+Make${name}View(${constructor_parameters} T &&emboss_reserved_local_arg) {
+  return Generic${name}View<
       /**/ ::emboss::support::ContiguousBuffer<
           typename ::std::remove_reference<decltype(
               *::std::declval<T>()->data())>::type,
           1, 0>>(
-      $_forwarded_parameters_$ ::std::forward<T>(emboss_reserved_local_arg));
+      ${forwarded_parameters} ::std::forward<T>(emboss_reserved_local_arg));
 }
 
 template <typename T>
-inline Generic$_name_$View</**/ ::emboss::support::ContiguousBuffer<T, 1, 0>>
-Make$_name_$View($_constructor_parameters_$ T *emboss_reserved_local_data,
+inline Generic${name}View</**/ ::emboss::support::ContiguousBuffer<T, 1, 0>>
+Make${name}View(${constructor_parameters} T *emboss_reserved_local_data,
                  ::std::size_t emboss_reserved_local_size) {
-  return Generic$_name_$View</**/ ::emboss::support::ContiguousBuffer<T, 1, 0>>(
-      $_forwarded_parameters_$ emboss_reserved_local_data,
+  return Generic${name}View</**/ ::emboss::support::ContiguousBuffer<T, 1, 0>>(
+      ${forwarded_parameters} emboss_reserved_local_data,
       emboss_reserved_local_size);
 }
 
 template <typename T, ::std::size_t kAlignment>
-inline Generic$_name_$View<
+inline Generic${name}View<
     /**/ ::emboss::support::ContiguousBuffer<T, kAlignment, 0>>
-MakeAligned$_name_$View(
-    $_constructor_parameters_$ T *emboss_reserved_local_data,
+MakeAligned${name}View(
+    ${constructor_parameters} T *emboss_reserved_local_data,
     ::std::size_t emboss_reserved_local_size) {
-  return Generic$_name_$View<
+  return Generic${name}View<
       /**/ ::emboss::support::ContiguousBuffer<T, kAlignment, 0>>(
-      $_forwarded_parameters_$ emboss_reserved_local_data,
+      ${forwarded_parameters} emboss_reserved_local_data,
       emboss_reserved_local_size);
 }
 
 // ** decode_field ** //////////////////////////////////////////////////////////
-      // If the field name matches $_field_name_$, handle it, otherwise fall
+      // If the field name matches ${field_name}, handle it, otherwise fall
       // through to the next field.
-      if (emboss_reserved_local_name == "$_field_name_$") {
+      if (emboss_reserved_local_name == "${field_name}") {
         // TODO(bolms): How should missing optional fields be handled?
-        if (!$_field_name_$().UpdateFromTextStream(
+        if (!${field_name}().UpdateFromTextStream(
                 emboss_reserved_local_stream)) {
           return false;
         }
@@ -310,12 +312,12 @@
       }
 
 // ** write_field_to_text_stream ** ////////////////////////////////////////////
-    if (has_$_field_name_$().ValueOr(false)) {
+    if (has_${field_name}().ValueOr(false)) {
       // Don't try to read the field if `allow_partial_output` is set and the
       // field can't be `Read()`.  Aggregates should still be visited, even if
       // they are not `Ok()` overall, since submembers may still be `Ok()`.
       if (!emboss_reserved_local_field_options.allow_partial_output() ||
-          $_field_name_$().IsAggregate() || $_field_name_$().Ok()) {
+          ${field_name}().IsAggregate() || ${field_name}().Ok()) {
         if (emboss_reserved_local_field_options.multiline()) {
           emboss_reserved_local_stream->Write(
               emboss_reserved_local_field_options.current_indent());
@@ -325,8 +327,8 @@
           }
           emboss_reserved_local_stream->Write(" ");
         }
-        emboss_reserved_local_stream->Write("$_field_name_$: ");
-        $_field_name_$().WriteToTextStream(emboss_reserved_local_stream,
+        emboss_reserved_local_stream->Write("${field_name}: ");
+        ${field_name}().WriteToTextStream(emboss_reserved_local_stream,
                                            emboss_reserved_local_field_options);
         emboss_reserved_local_wrote_field = true;
         if (emboss_reserved_local_field_options.multiline()) {
@@ -334,27 +336,27 @@
         }
       } else if (emboss_reserved_local_field_options.allow_partial_output() &&
                  emboss_reserved_local_field_options.comments() &&
-                 !$_field_name_$().IsAggregate() && !$_field_name_$().Ok()) {
+                 !${field_name}().IsAggregate() && !${field_name}().Ok()) {
         if (emboss_reserved_local_field_options.multiline()) {
           emboss_reserved_local_stream->Write(
               emboss_reserved_local_field_options.current_indent());
         }
-        emboss_reserved_local_stream->Write("# $_field_name_$: UNREADABLE\n");
+        emboss_reserved_local_stream->Write("# ${field_name}: UNREADABLE\n");
       }
     }
 
 // ** write_read_only_field_to_text_stream ** //////////////////////////////////
-    if (has_$_field_name_$().ValueOr(false) &&
+    if (has_${field_name}().ValueOr(false) &&
         emboss_reserved_local_field_options.comments()) {
       if (!emboss_reserved_local_field_options.allow_partial_output() ||
-          $_field_name_$().IsAggregate() || $_field_name_$().Ok()) {
+          ${field_name}().IsAggregate() || ${field_name}().Ok()) {
         emboss_reserved_local_stream->Write(
             emboss_reserved_local_field_options.current_indent());
         // TODO(bolms): When there are multiline read-only fields, add an option
         // to TextOutputOptions to add `# ` to the current indent and use it
         // here, so that subsequent lines are also commented out.
-        emboss_reserved_local_stream->Write("# $_field_name_$: ");
-        $_field_name_$().WriteToTextStream(emboss_reserved_local_stream,
+        emboss_reserved_local_stream->Write("# ${field_name}: ");
+        ${field_name}().WriteToTextStream(emboss_reserved_local_stream,
                                            emboss_reserved_local_field_options);
         emboss_reserved_local_stream->Write("\n");
       } else {
@@ -362,131 +364,131 @@
           emboss_reserved_local_stream->Write(
               emboss_reserved_local_field_options.current_indent());
         }
-        emboss_reserved_local_stream->Write("# $_field_name_$: UNREADABLE\n");
+        emboss_reserved_local_stream->Write("# ${field_name}: UNREADABLE\n");
       }
     }
 
 // ** constant_structure_size_method ** ////////////////////////////////////////
-  static constexpr ::std::size_t SizeIn$_units_$() {
-    return static_cast</**/ ::std::size_t>(IntrinsicSizeIn$_units_$().Read());
+  static constexpr ::std::size_t SizeIn${units}() {
+    return static_cast</**/ ::std::size_t>(IntrinsicSizeIn${units}().Read());
   }
   static constexpr bool SizeIsKnown() {
-    return IntrinsicSizeIn$_units_$().Ok();
+    return IntrinsicSizeIn${units}().Ok();
   }
 
 // ** runtime_structure_size_method ** /////////////////////////////////////////
-  ::std::size_t SizeIn$_units_$() const {
-    return static_cast</**/ ::std::size_t>(IntrinsicSizeIn$_units_$().Read());
+  ::std::size_t SizeIn${units}() const {
+    return static_cast</**/ ::std::size_t>(IntrinsicSizeIn${units}().Read());
   }
-  bool SizeIsKnown() const { return IntrinsicSizeIn$_units_$().Ok(); }
+  bool SizeIsKnown() const { return IntrinsicSizeIn${units}().Ok(); }
 
 
 // ** ok_method_test ** ////////////////////////////////////////////////////////
-    // If we don't have enough information to determine whether $_field_$ is
+    // If we don't have enough information to determine whether ${field} is
     // present in the structure, then structure.Ok() should be false.
-    if (!has_$_field_$.Known()) return false;
-    // If $_field_$ is present, but not Ok(), then structure.Ok() should be
-    // false.  If $_field_$ is not present, it does not matter whether it is
+    if (!has_${field}.Known()) return false;
+    // If ${field} is present, but not Ok(), then structure.Ok() should be
+    // false.  If ${field} is not present, it does not matter whether it is
     // Ok().
-    if (has_$_field_$.ValueOrDefault() && !$_field_$.Ok()) return false;
+    if (has_${field}.ValueOrDefault() && !${field}.Ok()) return false;
 
 
 // ** equals_method_test ** ////////////////////////////////////////////////////
-    // If this->$_field_$ is not equal to emboss_reserved_local_other.$_field_$,
+    // If this->${field} is not equal to emboss_reserved_local_other.${field},
     // then the structures are not equal.
 
-    // If either structure's has_$_field_$ is unknown, then default to not
+    // If either structure's has_${field} is unknown, then default to not
     // Equals().
     //
     // TODO(bolms): Should Equals() return Maybe<bool> and/or return true for
     // non-Ok()-but-equivalent structures?
-    if (!has_$_field_$.Known()) return false;
-    if (!emboss_reserved_local_other.has_$_field_$.Known()) return false;
+    if (!has_${field}.Known()) return false;
+    if (!emboss_reserved_local_other.has_${field}.Known()) return false;
 
-    // If one side has $_field_$ but the other side does not, then the fields
+    // If one side has ${field} but the other side does not, then the fields
     // are not equal.  We use ValueOrDefault() instead of Value() since Value()
     // is more complex and non-constexpr, and we already know that
-    // has_$_field_$.Known() is true for both structures.
-    if (emboss_reserved_local_other.has_$_field_$.ValueOrDefault() &&
-        !has_$_field_$.ValueOrDefault())
+    // has_${field}.Known() is true for both structures.
+    if (emboss_reserved_local_other.has_${field}.ValueOrDefault() &&
+        !has_${field}.ValueOrDefault())
       return false;
-    if (has_$_field_$.ValueOrDefault() &&
-        !emboss_reserved_local_other.has_$_field_$.ValueOrDefault())
+    if (has_${field}.ValueOrDefault() &&
+        !emboss_reserved_local_other.has_${field}.ValueOrDefault())
       return false;
 
-    // If both sides have $_field_$, then check that their Equals() returns
+    // If both sides have ${field}, then check that their Equals() returns
     // true.
-    if (emboss_reserved_local_other.has_$_field_$.ValueOrDefault() &&
-        has_$_field_$.ValueOrDefault() &&
-        !$_field_$.Equals(emboss_reserved_local_other.$_field_$))
+    if (emboss_reserved_local_other.has_${field}.ValueOrDefault() &&
+        has_${field}.ValueOrDefault() &&
+        !${field}.Equals(emboss_reserved_local_other.${field}))
       return false;
 
 
 // ** unchecked_equals_method_test ** //////////////////////////////////////////
     // The contract for UncheckedEquals() is that the caller must assure that
-    // both views are Ok() (which implies that has_$_field_$.Known() is true),
+    // both views are Ok() (which implies that has_${field}.Known() is true),
     // and UncheckedEquals() will never perform any assertion checks (which
-    // implies that UncheckedEquals() cannot call has_$_field_$.Value()).
+    // implies that UncheckedEquals() cannot call has_${field}.Value()).
 
-    // If this->has_$_field_$ but !emboss_reserved_local_other.has_$_field_$, or
+    // If this->has_${field} but !emboss_reserved_local_other.has_${field}, or
     // vice versa, then the structures are not equal.  If neither structure
-    // has_$_field_$, then $_field_$ is considered equal.
-    if (emboss_reserved_local_other.has_$_field_$.ValueOr(false) &&
-        !has_$_field_$.ValueOr(false))
+    // has_${field}, then ${field} is considered equal.
+    if (emboss_reserved_local_other.has_${field}.ValueOr(false) &&
+        !has_${field}.ValueOr(false))
       return false;
-    if (has_$_field_$.ValueOr(false) &&
-        !emboss_reserved_local_other.has_$_field_$.ValueOr(false))
+    if (has_${field}.ValueOr(false) &&
+        !emboss_reserved_local_other.has_${field}.ValueOr(false))
       return false;
 
-    // If $_field_$ is present in both structures, then check its equality.
-    if (emboss_reserved_local_other.has_$_field_$.ValueOr(false) &&
-        has_$_field_$.ValueOr(false) &&
-        !$_field_$.UncheckedEquals(emboss_reserved_local_other.$_field_$))
+    // If ${field} is present in both structures, then check its equality.
+    if (emboss_reserved_local_other.has_${field}.ValueOr(false) &&
+        has_${field}.ValueOr(false) &&
+        !${field}.UncheckedEquals(emboss_reserved_local_other.${field}))
       return false;
 
 
 // ** structure_view_type ** ///////////////////////////////////////////////////
-$_namespace_$::Generic$_name_$View<typename $_buffer_type_$>
+${namespace}::Generic${name}View<typename ${buffer_type}>
 
 
 // ** external_view_type ** ////////////////////////////////////////////////////
-$_namespace_$::$_name_$View<
-    /**/ ::emboss::support::FixedSizeViewParameters<$_bits_$, $_validator_$>,
-    typename $_buffer_type_$>
+${namespace}::${name}View<
+    /**/ ::emboss::support::FixedSizeViewParameters<${bits}, ${validator}>,
+    typename ${buffer_type}>
 
 
 // ** enum_view_type ** ////////////////////////////////////////////////////////
-$_support_namespace_$::EnumView<
-    /**/ $_enum_type_$,
-    ::emboss::support::FixedSizeViewParameters<$_bits_$, $_validator_$>,
-    typename $_buffer_type_$>
+${support_namespace}::EnumView<
+    /**/ ${enum_type},
+    ::emboss::support::FixedSizeViewParameters<${bits}, ${validator}>,
+    typename ${buffer_type}>
 
 
 // ** array_view_adapter ** ////////////////////////////////////////////////////
-$_support_namespace_$::GenericArrayView<
-    typename $_element_view_type_$, typename $_buffer_type_$, $_element_size_$,
-    $_addressable_unit_size_$ $_element_view_parameter_types_$>
+${support_namespace}::GenericArrayView<
+    typename ${element_view_type}, typename ${buffer_type}, ${element_size},
+    ${addressable_unit_size} ${element_view_parameter_types}>
 
 
 // ** structure_field_validator ** /////////////////////////////////////////////
-struct $_name_$ {
+struct ${name} {
   template <typename ValueType>
   static constexpr bool ValueIsOk(ValueType emboss_reserved_local_value) {
     (void)emboss_reserved_local_value;  // Silence -Wunused-parameter
-    return ($_expression_$).ValueOrDefault();
+    return (${expression}).ValueOrDefault();
   }
 };
 
 
 // ** structure_single_field_method_declarations ** ////////////////////////////
- $_visibility_$:
-  typename $_type_reader_$ $_name_$() const;
-  ::emboss::support::Maybe<bool> has_$_name_$() const;
+ ${visibility}:
+  typename ${type_reader} ${name}() const;
+  ::emboss::support::Maybe<bool> has_${name}() const;
 
 
 // ** structure_single_field_method_definitions ** /////////////////////////////
 template <class Storage>
-inline typename $_type_reader_$ Generic$_parent_type_$View<Storage>::$_name_$()
+inline typename ${type_reader} Generic${parent_type}View<Storage>::${name}()
     const {
   // If it's not possible to read the location of this field, provide a view
   // into a null storage -- the only safe methods to call on it will be Ok() and
@@ -494,116 +496,116 @@
   // call those methods at all.  Similarly, if the end of the field would come
   // before the start, we provide a null storage, though arguably we should
   // not.
-$_parameter_subexpressions_$
-  if ($_parameters_known_$ has_$_name_$().ValueOr(false)) {
-$_size_and_offset_subexpressions_$
-    auto emboss_reserved_local_size = $_size_$;
-    auto emboss_reserved_local_offset = $_offset_$;
+${parameter_subexpressions}
+  if (${parameters_known} has_${name}().ValueOr(false)) {
+${size_and_offset_subexpressions}
+    auto emboss_reserved_local_size = ${size};
+    auto emboss_reserved_local_offset = ${offset};
     if (emboss_reserved_local_size.Known() &&
         emboss_reserved_local_size.ValueOr(0) >= 0 &&
         emboss_reserved_local_offset.Known() &&
         emboss_reserved_local_offset.ValueOr(0) >= 0) {
-        return $_type_reader_$(
-                $_parameter_values_$ backing_
-                        .template GetOffsetStorage<$_alignment_$,
-                                                   $_static_offset_$>(
+        return ${type_reader}(
+                ${parameter_values} backing_
+                        .template GetOffsetStorage<${alignment},
+                                                   ${static_offset}>(
                                 emboss_reserved_local_offset.ValueOrDefault(),
                                 emboss_reserved_local_size.ValueOrDefault()));
     }
   }
-  return $_type_reader_$();
+  return ${type_reader}();
 }
 
 template <class Storage>
 inline ::emboss::support::Maybe<bool>
-Generic$_parent_type_$View<Storage>::has_$_name_$() const {
-  return $_field_exists_$;
+Generic${parent_type}View<Storage>::has_${name}() const {
+  return ${field_exists};
 }
 
 
 // ** structure_single_const_virtual_field_method_declarations ** //////////////
- $_visibility_$:
-  class $_virtual_view_type_name_$ final {
+ ${visibility}:
+  class ${virtual_view_type_name} final {
    public:
-    using ValueType = $_logical_type_$;
+    using ValueType = ${logical_type};
 
-    constexpr $_virtual_view_type_name_$() {}
-    $_virtual_view_type_name_$(const $_virtual_view_type_name_$ &) = default;
-    $_virtual_view_type_name_$($_virtual_view_type_name_$ &&) = default;
-    $_virtual_view_type_name_$ &operator=(const $_virtual_view_type_name_$ &) =
+    constexpr ${virtual_view_type_name}() {}
+    ${virtual_view_type_name}(const ${virtual_view_type_name} &) = default;
+    ${virtual_view_type_name}(${virtual_view_type_name} &&) = default;
+    ${virtual_view_type_name} &operator=(const ${virtual_view_type_name} &) =
         default;
-    $_virtual_view_type_name_$ &operator=($_virtual_view_type_name_$ &&) =
+    ${virtual_view_type_name} &operator=(${virtual_view_type_name} &&) =
         default;
-    ~$_virtual_view_type_name_$() = default;
+    ~${virtual_view_type_name}() = default;
 
-    static constexpr $_logical_type_$ Read();
-    static constexpr $_logical_type_$ UncheckedRead();
+    static constexpr ${logical_type} Read();
+    static constexpr ${logical_type} UncheckedRead();
     static constexpr bool Ok() { return true; }
     template <class Stream>
     void WriteToTextStream(Stream *emboss_reserved_local_stream,
                            const ::emboss::TextOutputOptions
                                &emboss_reserved_local_options) const {
-      ::emboss::support::$_write_to_text_stream_function_$(
+      ::emboss::support::${write_to_text_stream_function}(
           this, emboss_reserved_local_stream, emboss_reserved_local_options);
     }
 
     static constexpr bool IsAggregate() { return false; }
   };
 
-  static constexpr $_virtual_view_type_name_$ $_name_$() {
-    return $_virtual_view_type_name_$();
+  static constexpr ${virtual_view_type_name} ${name}() {
+    return ${virtual_view_type_name}();
   }
-  static constexpr ::emboss::support::Maybe<bool> has_$_name_$() {
+  static constexpr ::emboss::support::Maybe<bool> has_${name}() {
     return ::emboss::support::Maybe<bool>(true);
   }
 
 
 // ** structure_single_const_virtual_field_method_definitions ** ///////////////
-namespace $_parent_type_$ {
-inline constexpr $_logical_type_$ $_name_$() {
-  return $_read_value_$.ValueOrDefault();
+namespace ${parent_type} {
+inline constexpr ${logical_type} ${name}() {
+  return ${read_value}.ValueOrDefault();
 }
-}  // namespace $_parent_type_$
+}  // namespace ${parent_type}
 
 template <class Storage>
-inline constexpr $_logical_type_$
-Generic$_parent_type_$View<Storage>::$_virtual_view_type_name_$::Read() {
-  return $_parent_type_$::$_name_$();
+inline constexpr ${logical_type}
+Generic${parent_type}View<Storage>::${virtual_view_type_name}::Read() {
+  return ${parent_type}::${name}();
 }
 
 template <class Storage>
-inline constexpr $_logical_type_$
-Generic$_parent_type_$View<
-    Storage>::$_virtual_view_type_name_$::UncheckedRead() {
-  return $_parent_type_$::$_name_$();
+inline constexpr ${logical_type}
+Generic${parent_type}View<
+    Storage>::${virtual_view_type_name}::UncheckedRead() {
+  return ${parent_type}::${name}();
 }
 
 // ** structure_single_virtual_field_method_declarations ** ////////////////////
- $_visibility_$:
-  class $_virtual_view_type_name_$ final {
+ ${visibility}:
+  class ${virtual_view_type_name} final {
    public:
-    using ValueType = $_logical_type_$;
+    using ValueType = ${logical_type};
 
-    explicit $_virtual_view_type_name_$(
-        const Generic$_parent_type_$View &emboss_reserved_local_view)
+    explicit ${virtual_view_type_name}(
+        const Generic${parent_type}View &emboss_reserved_local_view)
         : view_(emboss_reserved_local_view) {}
-    $_virtual_view_type_name_$() = delete;
-    $_virtual_view_type_name_$(const $_virtual_view_type_name_$ &) = default;
-    $_virtual_view_type_name_$($_virtual_view_type_name_$ &&) = default;
-    $_virtual_view_type_name_$ &operator=(const $_virtual_view_type_name_$ &) =
+    ${virtual_view_type_name}() = delete;
+    ${virtual_view_type_name}(const ${virtual_view_type_name} &) = default;
+    ${virtual_view_type_name}(${virtual_view_type_name} &&) = default;
+    ${virtual_view_type_name} &operator=(const ${virtual_view_type_name} &) =
         default;
-    $_virtual_view_type_name_$ &operator=($_virtual_view_type_name_$ &&) =
+    ${virtual_view_type_name} &operator=(${virtual_view_type_name} &&) =
         default;
-    ~$_virtual_view_type_name_$() = default;
+    ~${virtual_view_type_name}() = default;
 
-    $_logical_type_$ Read() const {
-      EMBOSS_CHECK(view_.has_$_name_$().ValueOr(false));
+    ${logical_type} Read() const {
+      EMBOSS_CHECK(view_.has_${name}().ValueOr(false));
       auto emboss_reserved_local_value = MaybeRead();
       EMBOSS_CHECK(emboss_reserved_local_value.Known());
       EMBOSS_CHECK(ValueIsOk(emboss_reserved_local_value.ValueOrDefault()));
       return emboss_reserved_local_value.ValueOrDefault();
     }
-    $_logical_type_$ UncheckedRead() const {
+    ${logical_type} UncheckedRead() const {
       // UncheckedRead() on a virtual still calls Ok() on its dependencies;
       // i.e., it still does some bounds checking.  This is because of a subtle
       // case, illustrated by the example below:
@@ -646,52 +648,52 @@
     void WriteToTextStream(Stream *emboss_reserved_local_stream,
                            const ::emboss::TextOutputOptions
                                &emboss_reserved_local_options) const {
-      ::emboss::support::$_write_to_text_stream_function_$(
+      ::emboss::support::${write_to_text_stream_function}(
           this, emboss_reserved_local_stream, emboss_reserved_local_options);
     }
 
     static constexpr bool IsAggregate() { return false; }
 
-$_write_methods_$
+${write_methods}
 
    private:
-    ::emboss::support::Maybe</**/ $_logical_type_$> MaybeRead() const {
-$_read_subexpressions_$
-      return $_read_value_$;
+    ::emboss::support::Maybe</**/ ${logical_type}> MaybeRead() const {
+${read_subexpressions}
+      return ${read_value};
     }
 
     static constexpr bool ValueIsOk(
-        $_logical_type_$ emboss_reserved_local_value) {
+        ${logical_type} emboss_reserved_local_value) {
       (void)emboss_reserved_local_value;  // Silence -Wunused-parameter
-      return $_value_is_ok_$.ValueOr(false);
+      return ${value_is_ok}.ValueOr(false);
     }
 
-    const Generic$_parent_type_$View view_;
+    const Generic${parent_type}View view_;
   };
-  $_virtual_view_type_name_$ $_name_$() const;
-  ::emboss::support::Maybe<bool> has_$_name_$() const;
+  ${virtual_view_type_name} ${name}() const;
+  ::emboss::support::Maybe<bool> has_${name}() const;
 
 
 // ** structure_single_virtual_field_write_methods ** //////////////////////////
-    bool TryToWrite($_logical_type_$ emboss_reserved_local_value) {
-      const auto emboss_reserved_local_maybe_new_value = $_transform_$;
+    bool TryToWrite(${logical_type} emboss_reserved_local_value) {
+      const auto emboss_reserved_local_maybe_new_value = ${transform};
       if (!CouldWriteValue(emboss_reserved_local_value)) return false;
-      return view_.$_destination_$.TryToWrite(
+      return view_.${destination}.TryToWrite(
           emboss_reserved_local_maybe_new_value.ValueOrDefault());
     }
-    void Write($_logical_type_$ emboss_reserved_local_value) {
+    void Write(${logical_type} emboss_reserved_local_value) {
       const bool result = TryToWrite(emboss_reserved_local_value);
       (void)result;
       EMBOSS_CHECK(result);
     }
-    void UncheckedWrite($_logical_type_$ emboss_reserved_local_value) {
-      view_.$_destination_$.UncheckedWrite(($_transform_$).ValueOrDefault());
+    void UncheckedWrite(${logical_type} emboss_reserved_local_value) {
+      view_.${destination}.UncheckedWrite((${transform}).ValueOrDefault());
     }
-    bool CouldWriteValue($_logical_type_$ emboss_reserved_local_value) {
+    bool CouldWriteValue(${logical_type} emboss_reserved_local_value) {
       if (!ValueIsOk(emboss_reserved_local_value)) return false;
-      const auto emboss_reserved_local_maybe_new_value = $_transform_$;
+      const auto emboss_reserved_local_maybe_new_value = ${transform};
       if (!emboss_reserved_local_maybe_new_value.Known()) return false;
-      return view_.$_destination_$.CouldWriteValue(
+      return view_.${destination}.CouldWriteValue(
           emboss_reserved_local_maybe_new_value.ValueOrDefault());
     }
     template <class Stream>
@@ -703,60 +705,60 @@
 
 // ** structure_single_virtual_field_method_definitions ** /////////////////////
 template <class Storage>
-inline typename Generic$_parent_type_$View<Storage>::$_virtual_view_type_name_$
-Generic$_parent_type_$View<Storage>::$_name_$() const {
+inline typename Generic${parent_type}View<Storage>::${virtual_view_type_name}
+Generic${parent_type}View<Storage>::${name}() const {
   return
-      typename Generic$_parent_type_$View<Storage>::$_virtual_view_type_name_$(
+      typename Generic${parent_type}View<Storage>::${virtual_view_type_name}(
           *this);
 }
 
 template <class Storage>
 inline ::emboss::support::Maybe<bool>
-Generic$_parent_type_$View<Storage>::has_$_name_$() const {
-  return $_field_exists_$;
+Generic${parent_type}View<Storage>::has_${name}() const {
+  return ${field_exists};
 }
 
 
 // ** structure_single_field_indirect_method_declarations ** ///////////////////
- $_visibility_$:
+ ${visibility}:
   // The "this->" is required for (some versions of?) GCC.
-  auto $_name_$() const -> decltype(this->$_aliased_field_$) {
-   return has_$_name_$().ValueOrDefault() ? $_aliased_field_$
-                                          : decltype(this->$_aliased_field_$)();
+  auto ${name}() const -> decltype(this->${aliased_field}) {
+   return has_${name}().ValueOrDefault() ? ${aliased_field}
+                                          : decltype(this->${aliased_field})();
   }
-  ::emboss::support::Maybe<bool> has_$_name_$() const;
+  ::emboss::support::Maybe<bool> has_${name}() const;
 
 
 // ** struct_single_field_indirect_method_definitions ** ///////////////////////
 template <class Storage>
 inline ::emboss::support::Maybe<bool>
-Generic$_parent_type_$View<Storage>::has_$_name_$() const {
-  return $_field_exists_$;
+Generic${parent_type}View<Storage>::has_${name}() const {
+  return ${field_exists};
 }
 
 
 // ** structure_single_parameter_field_method_declarations ** //////////////////
  private:
   // TODO(bolms): Is there any harm if these are public methods?
-  constexpr ::emboss::support::MaybeConstantView</**/ $_logical_type_$>
-  $_name_$() const {
+  constexpr ::emboss::support::MaybeConstantView</**/ ${logical_type}>
+  ${name}() const {
     return parameters_initialized_
-               ? ::emboss::support::MaybeConstantView</**/ $_logical_type_$>(
-                     $_name_$_)
-               : ::emboss::support::MaybeConstantView</**/ $_logical_type_$>();
+               ? ::emboss::support::MaybeConstantView</**/ ${logical_type}>(
+                     ${name}_)
+               : ::emboss::support::MaybeConstantView</**/ ${logical_type}>();
   }
-  constexpr ::emboss::support::Maybe<bool> has_$_name_$() const {
+  constexpr ::emboss::support::Maybe<bool> has_${name}() const {
     return ::emboss::support::Maybe<bool>(parameters_initialized_);
   }
 
 
 // ** enum_declaration ** //////////////////////////////////////////////////////
-enum class $_enum_$ : $_enum_type_$;
+enum class ${enum} : ${enum_type};
 
 
 // ** enum_definition ** ///////////////////////////////////////////////////////
-enum class $_enum_$ : $_enum_type_$ {
-$_enum_values_$
+enum class ${enum} : ${enum_type} {
+${enum_values}
 };
 
 // This setup (ab)uses the fact that C++ templates can be defined in many
@@ -772,41 +774,41 @@
 class EnumTraits;
 
 template <>
-class EnumTraits<$_enum_$> final {
+class EnumTraits<${enum}> final {
  public:
   static bool TryToGetEnumFromName(const char *emboss_reserved_local_name,
-                                   $_enum_$ *emboss_reserved_local_result) {
+                                   ${enum} *emboss_reserved_local_result) {
     if (emboss_reserved_local_name == nullptr) return false;
     // TODO(bolms): The generated code here would be much more efficient for
     // large enums if the mapping were performed using a prefix trie rather than
     // repeated strcmp().
-$_enum_from_name_cases_$
+${enum_from_name_cases}
     return false;
   }
 
   static const char *TryToGetNameFromEnum(
-      $_enum_$ emboss_reserved_local_value) {
+      ${enum} emboss_reserved_local_value) {
     switch (emboss_reserved_local_value) {
-$_name_from_enum_cases_$
+${name_from_enum_cases}
       default: return nullptr;
     }
   }
 
-  static bool EnumIsKnown($_enum_$ emboss_reserved_local_value) {
+  static bool EnumIsKnown(${enum} emboss_reserved_local_value) {
     switch (emboss_reserved_local_value) {
-$_enum_is_known_cases_$
+${enum_is_known_cases}
       default:
         return false;
     }
   }
 
   static ::std::ostream &SendToOstream(::std::ostream &emboss_reserved_local_os,
-                                       $_enum_$ emboss_reserved_local_value) {
+                                       ${enum} emboss_reserved_local_value) {
     const char *emboss_reserved_local_name =
         TryToGetNameFromEnum(emboss_reserved_local_value);
     if (emboss_reserved_local_name == nullptr) {
       emboss_reserved_local_os
-          << static_cast</**/ ::std::underlying_type<$_enum_$>::type>(
+          << static_cast</**/ ::std::underlying_type<${enum}>::type>(
                  emboss_reserved_local_value);
     } else {
       emboss_reserved_local_os << emboss_reserved_local_name;
@@ -818,42 +820,42 @@
 // These functions are intended to be found via ADL.
 static inline bool TryToGetEnumFromName(
     const char *emboss_reserved_local_name,
-    $_enum_$ *emboss_reserved_local_result) {
-  return EnumTraits<$_enum_$>::TryToGetEnumFromName(
+    ${enum} *emboss_reserved_local_result) {
+  return EnumTraits<${enum}>::TryToGetEnumFromName(
       emboss_reserved_local_name, emboss_reserved_local_result);
 }
 
 static inline const char *TryToGetNameFromEnum(
-    $_enum_$ emboss_reserved_local_value) {
-  return EnumTraits<$_enum_$>::TryToGetNameFromEnum(
+    ${enum} emboss_reserved_local_value) {
+  return EnumTraits<${enum}>::TryToGetNameFromEnum(
       emboss_reserved_local_value);
 }
 
-static inline bool EnumIsKnown($_enum_$ emboss_reserved_local_value) {
-  return EnumTraits<$_enum_$>::EnumIsKnown(emboss_reserved_local_value);
+static inline bool EnumIsKnown(${enum} emboss_reserved_local_value) {
+  return EnumTraits<${enum}>::EnumIsKnown(emboss_reserved_local_value);
 }
 
 static inline ::std::ostream &operator<<(
     ::std::ostream &emboss_reserved_local_os,
-    $_enum_$ emboss_reserved_local_value) {
-  return EnumTraits<$_enum_$>::SendToOstream(emboss_reserved_local_os,
+    ${enum} emboss_reserved_local_value) {
+  return EnumTraits<${enum}>::SendToOstream(emboss_reserved_local_os,
                                              emboss_reserved_local_value);
 }
 
 // ** enum_from_name_case ** ///////////////////////////////////////////////////
-    if (!strcmp("$_name_$", emboss_reserved_local_name)) {
-      *emboss_reserved_local_result = $_enum_$::$_value_$;
+    if (!strcmp("${name}", emboss_reserved_local_name)) {
+      *emboss_reserved_local_result = ${enum}::${value};
       return true;
     }
 
 // ** name_from_enum_case ** ///////////////////////////////////////////////////
-      case $_enum_$::$_value_$: return "$_name_$";
+      case ${enum}::${value}: return "${name}";
 
 // ** enum_is_known_case ** ////////////////////////////////////////////////////
-      case $_enum_$::$_name_$: return true;
+      case ${enum}::${name}: return true;
 
 // ** enum_value ** ////////////////////////////////////////////////////////////
-  $_name_$ = $_value_$,
+  ${name} = ${value},
 
 // ** enum_using_statement ** //////////////////////////////////////////////////
-  using $_name_$ = $_component_$;
+  using ${name} = ${component};
diff --git a/compiler/back_end/util/code_template.py b/compiler/back_end/util/code_template.py
index bbea043..5374676 100644
--- a/compiler/back_end/util/code_template.py
+++ b/compiler/back_end/util/code_template.py
@@ -22,82 +22,25 @@
 import string
 
 
-class _CppFormatter(string.Formatter):
-  """Customized Formatter using $_name_$ instead of {name}.
-
-  This class exists for the format_template() function; see its documentation
-  for details.
-  """
-
-  def parse(self, format_string):
-    """Overrides string.Formatter.parse.
-
-    Arguments:
-      format_string: a format string to be parsed.
-
-    Yields:
-      A sequence of 4-element tuples (literal, name, format_spec, conversion),
-      where:
-
-        literal: A literal string to include in the output.  This will be
-          output before the substitution, if any.
-        name: The name of a substitution, or None if no substitution.
-        format_spec: A format specification.
-        conversion: A conversion specification.
-
-      Consult the documentation for string.Formatter for the format of the
-      format_spec and conversion elements.
-    """
-    # A replacement spec is $_field_name!conversion:format_spec_$, where
-    # conversion and format_spec are optional.  string.Formatter will take care
-    # of parsing and interpreting the conversion and format_spec, so this method
-    # just extracts them.
-    delimiter_matches = re.finditer(
-        r"""(?x)
-            \$_
-                  (?P<field_name>  ( [^!:_] | _[^$] )* )
-              ( ! (?P<conversion>  ( [^:_]  | _[^$] )* ) )?
-              ( : (?P<format_spec> ( [^_]   | _[^$] )* ) )?
-            _\$""", format_string)
-    after_last_delimiter = 0
-    for match in delimiter_matches:
-      yield (format_string[after_last_delimiter:match.start()],
-             match.group("field_name"),
-             # A missing format_spec is indicated by ""...
-             match.group("format_spec") or "",
-             # ... but a missing conversion is indicated by None.  Consistency!
-             match.group("conversion") or None)
-      after_last_delimiter = match.end()
-    yield format_string[after_last_delimiter:], None, None, None
-
-
-_FORMATTER = _CppFormatter()
-
-
-def format_template(template, *args, **kwargs):
-  """format_template acts like str.format, but uses $_name_$ instead of {name}.
+def format_template(template, **kwargs):
+  """format_template acts like str.format, but uses ${name} instead of {name}.
 
   format_template acts like a str.format, except that instead of using { and }
-  to delimit substitutions, format_template uses $_ and _$.  This simplifies
+  to delimit substitutions, format_template uses ${name}.  This simplifies
   templates of source code in most languages, which frequently use "{" and "}",
-  but very rarely use "$".  The choice of "$_" and "_$" is conducive to the use
-  of clang-format on templates.
+  but very rarely use "$".
 
-  format_template does not currently have a way to put literal "$_..._$" into a
-  format string.
-
-  See the documentation for str.format and string.Formatter for details about
+  See the documentation for string.Template for details about
   template strings and the format of substitutions.
 
   Arguments:
     template: A template to format.
-    *args: Positional arguments for string.Formatter.format.
-    **kwargs: Keyword arguments for string.Formatter.format.
+    **kwargs: Keyword arguments for string.Template.substitute.
 
   Returns:
     A formatted string.
   """
-  return _FORMATTER.format(template, *args, **kwargs)
+  return template.substitute(**kwargs)
 
 
 def parse_templates(text):
@@ -126,15 +69,18 @@
   templates = {}
   name = None
   template = []
+  def finish_template(template):
+    return string.Template("\n".join(template))
+
   for line in text.splitlines():
     if delimiter_re.match(line):
       if name:
-        templates[name] = "\n".join(template)
+        templates[name] = finish_template(template)
       name = delimiter_re.match(line).group(1)
       template = []
     else:
       template.append(line)
   if name:
-    templates[name] = "\n".join(template)
+    templates[name] = finish_template(template)
   return collections.namedtuple("Templates",
                                 list(templates.keys()))(**templates)
diff --git a/compiler/back_end/util/code_template_test.py b/compiler/back_end/util/code_template_test.py
index 31e1400..c133096 100644
--- a/compiler/back_end/util/code_template_test.py
+++ b/compiler/back_end/util/code_template_test.py
@@ -14,48 +14,41 @@
 
 """Tests for code_template."""
 
+import string
 import unittest
 from compiler.back_end.util import code_template
 
+def _format_template_str(template: str, **kwargs) -> str:
+  return code_template.format_template(string.Template(template), **kwargs)
 
 class FormatTest(unittest.TestCase):
   """Tests for code_template.format."""
 
   def test_no_replacement_fields(self):
-    self.assertEqual("foo", code_template.format_template("foo"))
-    self.assertEqual("{foo}", code_template.format_template("{foo}"))
-    self.assertEqual("$foo$", code_template.format_template("$foo$"))
-    self.assertEqual("$_foo$", code_template.format_template("$_foo$"))
-    self.assertEqual("$foo_$", code_template.format_template("$foo_$"))
+    self.assertEqual("foo", _format_template_str("foo"))
+    self.assertEqual("{foo}", _format_template_str("{foo}"))
+    self.assertEqual("${foo}", _format_template_str("$${foo}"))
 
   def test_one_replacement_field(self):
-    self.assertEqual("foo", code_template.format_template("$_bar_$", bar="foo"))
+    self.assertEqual("foo", _format_template_str("${bar}", bar="foo"))
     self.assertEqual("bazfoo",
-                     code_template.format_template("baz$_bar_$", bar="foo"))
+                     _format_template_str("baz${bar}", bar="foo"))
     self.assertEqual("foobaz",
-                     code_template.format_template("$_bar_$baz", bar="foo"))
+                     _format_template_str("${bar}baz", bar="foo"))
     self.assertEqual("bazfooqux",
-                     code_template.format_template("baz$_bar_$qux", bar="foo"))
+                     _format_template_str("baz${bar}qux", bar="foo"))
 
   def test_one_replacement_field_with_formatting(self):
-    self.assertEqual("1.000000",
-                     code_template.format_template("$_bar:.6f_$", bar=1))
-    self.assertEqual("'foo'",
-                     code_template.format_template("$_bar!r_$", bar="foo"))
-    self.assertEqual("==foo==",
-                     code_template.format_template("$_bar:=^7_$", bar="foo"))
-    self.assertEqual("=='foo'==",
-                     code_template.format_template("$_bar!r:=^9_$", bar="foo"))
-    self.assertEqual("xx=='foo'==yy",
-                     code_template.format_template("xx$_bar!r:=^9_$yy",
-                                                   bar="foo"))
+    # Basic string.Templates don't support formatting values.
+    self.assertRaises(ValueError,
+                     _format_template_str, "${bar:.6f}", bar=1)
 
   def test_one_replacement_field_value_missing(self):
-    self.assertRaises(KeyError, code_template.format_template, "$_bar_$")
+    self.assertRaises(KeyError, _format_template_str, "${bar}")
 
   def test_multiple_replacement_fields(self):
     self.assertEqual(" aaa  bbb   ",
-                     code_template.format_template(" $_bar_$  $_baz_$   ",
+                     _format_template_str(" ${bar}  ${baz}   ",
                                                    bar="aaa",
                                                    baz="bbb"))
 
@@ -63,36 +56,44 @@
 class ParseTemplatesTest(unittest.TestCase):
   """Tests for code_template.parse_templates."""
 
+  def assertTemplatesEqual(self, expected, actual): # pylint:disable=invalid-name
+    """Compares the results of a parse_templates"""
+    # Extract the name and template from the result tuple
+    actual = {
+        k: v.template for k, v in actual._asdict().items()
+    }
+    self.assertEqual(expected, actual)
+
   def test_handles_no_template_case(self):
-    self.assertEqual({}, code_template.parse_templates("")._asdict())
-    self.assertEqual({}, code_template.parse_templates(
-        "this is not a template")._asdict())
+    self.assertTemplatesEqual({}, code_template.parse_templates(""))
+    self.assertTemplatesEqual({}, code_template.parse_templates(
+        "this is not a template"))
 
   def test_handles_one_template_at_start(self):
-    self.assertEqual({"foo": "bar"},
-                     code_template.parse_templates("** foo **\nbar")._asdict())
+    self.assertTemplatesEqual({"foo": "bar"},
+                     code_template.parse_templates("** foo **\nbar"))
 
   def test_handles_one_template_after_start(self):
-    self.assertEqual(
+    self.assertTemplatesEqual(
         {"foo": "bar"},
-        code_template.parse_templates("text\n** foo **\nbar")._asdict())
+        code_template.parse_templates("text\n** foo **\nbar"))
 
   def test_handles_delimiter_with_other_text(self):
-    self.assertEqual(
+    self.assertTemplatesEqual(
         {"foo": "bar"},
-        code_template.parse_templates("text\n// ** foo ** ////\nbar")._asdict())
-    self.assertEqual(
+        code_template.parse_templates("text\n// ** foo ** ////\nbar"))
+    self.assertTemplatesEqual(
         {"foo": "bar"},
-        code_template.parse_templates("text\n# ** foo ** #####\nbar")._asdict())
+        code_template.parse_templates("text\n# ** foo ** #####\nbar"))
 
   def test_handles_multiple_delimiters(self):
-    self.assertEqual({"foo": "bar",
+    self.assertTemplatesEqual({"foo": "bar",
                       "baz": "qux"}, code_template.parse_templates(
-                          "** foo **\nbar\n** baz **\nqux")._asdict())
+                          "** foo **\nbar\n** baz **\nqux"))
 
   def test_returns_object_with_attributes(self):
     self.assertEqual("bar", code_template.parse_templates(
-        "** foo **\nbar\n** baz **\nqux").foo)
+        "** foo **\nbar\n** baz **\nqux").foo.template)
 
 if __name__ == "__main__":
   unittest.main()