writer/msl: Rework string printing

Add `out` parameters to expression and type generators.

Use the new helper classes in TextGenerator.
Cleans up bad formatting.

Prepares the writer generating 'pre' statements, required for atomics.

If-else statements are generated slightly differently. This is done so that 'pre' statements for the else conditions are scoped correctly. This is identical to the HLSL writer.

Bug tint:892

Change-Id: I4c6e96c90673ba30898b3682bf3198497d63a2d4
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56067
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/test/intrinsics/gen/dpdx/0763f7.wgsl.expected.msl b/test/intrinsics/gen/dpdx/0763f7.wgsl.expected.msl
index 082d924..a7719d7 100644
--- a/test/intrinsics/gen/dpdx/0763f7.wgsl.expected.msl
+++ b/test/intrinsics/gen/dpdx/0763f7.wgsl.expected.msl
@@ -2,7 +2,7 @@
 
 using namespace metal;
 void dpdx_0763f7() {
-  float3 res =   dfdx(float3());
+  float3 res = dfdx(float3());
 }
 
 fragment void fragment_main() {