Revert "Revert "SkSL DSL now reports the C++ line numbers of errors""

This reverts commit 3a4e19da8e9656c1f82e29d70a2bb3b2f92c6c0b.

TBR=brianosman@google.com, johnstiles@google.com

Change-Id: I5ae97aba2df5b9c3b3dcca8e30da4e5ce9009109
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/376117
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/gn/tests.gni b/gn/tests.gni
index bd55bd2..7bb9d2c 100644
--- a/gn/tests.gni
+++ b/gn/tests.gni
@@ -261,6 +261,7 @@
   "$_tests/SkResourceCacheTest.cpp",
   "$_tests/SkRuntimeEffectTest.cpp",
   "$_tests/SkSLCross.cpp",
+  "$_tests/SkSLDSLErrorLineNumbers.cpp",
   "$_tests/SkSLDSLTest.cpp",
   "$_tests/SkSLFPTestbed.cpp",
   "$_tests/SkSLGLSLTestbed.cpp",
diff --git a/src/sksl/dsl/DSLCore.cpp b/src/sksl/dsl/DSLCore.cpp
index 0f84b48..7b98cb2 100644
--- a/src/sksl/dsl/DSLCore.cpp
+++ b/src/sksl/dsl/DSLCore.cpp
@@ -51,7 +51,7 @@
     }
 
     template <typename... Args>
-    static DSLExpression Call(const char* name, Args... args) {
+    static DSLPossibleExpression Call(const char* name, Args... args) {
         SkSL::IRGenerator& ir = DSLWriter::IRGenerator();
         SkSL::ExpressionArray argArray;
         argArray.reserve_back(sizeof...(args));
@@ -72,10 +72,10 @@
         return std::unique_ptr<SkSL::Statement>(new SkSL::ContinueStatement(/*offset=*/-1));
     }
 
-    static DSLStatement Declare(DSLVar& var, DSLExpression initialValue) {
+    static DSLPossibleStatement Declare(DSLVar& var, DSLExpression initialValue) {
         if (var.fConstVar) {
             DSLWriter::ReportError("Variable already declared");
-            return DSLStatement();
+            return DSLPossibleStatement(nullptr);
         }
         SkASSERT(var.fVar);
         var.fConstVar = var.fVar.get();
@@ -87,23 +87,23 @@
         return std::unique_ptr<SkSL::Statement>(new SkSL::DiscardStatement(/*offset=*/-1));
     }
 
-    static DSLStatement Do(DSLStatement stmt, DSLExpression test) {
+    static DSLPossibleStatement Do(DSLStatement stmt, DSLExpression test) {
         return DSLWriter::IRGenerator().convertDo(stmt.release(), test.release());
     }
 
-    static DSLStatement For(DSLStatement initializer, DSLExpression test, DSLExpression next,
-                            DSLStatement stmt) {
+    static DSLPossibleStatement For(DSLStatement initializer, DSLExpression test,
+                                    DSLExpression next, DSLStatement stmt) {
         return ForStatement::Make(DSLWriter::Context(), /*offset=*/-1, initializer.release(),
                                   test.release(), next.release(), stmt.release(),
                                   DSLWriter::SymbolTable());
     }
 
-    static DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse) {
+    static DSLPossibleStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse) {
         return IfStatement::Make(DSLWriter::Context(), /*offset=*/-1, /*isStatic=*/false,
                                  test.release(), ifTrue.release(), ifFalse.release());
     }
 
-    static DSLStatement Return(DSLExpression value) {
+    static DSLPossibleStatement Return(DSLExpression value, PositionInfo pos) {
         // note that because Return is called before the function in which it resides exists, at
         // this point we do not know the function's return type. We therefore do not check for
         // errors, or coerce the value to the correct type, until the return statement is actually
@@ -116,37 +116,51 @@
         }
     }
 
-    static DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a) {
-        return Swizzle::MakeWith01(DSLWriter::Context(), base.release(), ComponentArray{a});
-    }
-
-    static DSLExpression Swizzle(DSLExpression base,
-                                 SkSL::SwizzleComponent::Type a,
-                                 SkSL::SwizzleComponent::Type b) {
-        return Swizzle::MakeWith01(DSLWriter::Context(), base.release(), ComponentArray{a, b});
+    static DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a,
+                                 PositionInfo pos) {
+        return DSLExpression(Swizzle::MakeWith01(DSLWriter::Context(), base.release(),
+                                                 ComponentArray{a}),
+                             pos);
     }
 
     static DSLExpression Swizzle(DSLExpression base,
                                  SkSL::SwizzleComponent::Type a,
                                  SkSL::SwizzleComponent::Type b,
-                                 SkSL::SwizzleComponent::Type c) {
-        return Swizzle::MakeWith01(DSLWriter::Context(), base.release(), ComponentArray{a, b, c});
+                                 PositionInfo pos) {
+        return DSLExpression(Swizzle::MakeWith01(DSLWriter::Context(), base.release(),
+                                                 ComponentArray{a, b}),
+                             pos);
     }
 
     static DSLExpression Swizzle(DSLExpression base,
                                  SkSL::SwizzleComponent::Type a,
                                  SkSL::SwizzleComponent::Type b,
                                  SkSL::SwizzleComponent::Type c,
-                                 SkSL::SwizzleComponent::Type d) {
-        return Swizzle::MakeWith01(DSLWriter::Context(), base.release(), ComponentArray{a,b,c,d});
+                                 PositionInfo pos) {
+        return DSLExpression(Swizzle::MakeWith01(DSLWriter::Context(), base.release(),
+                                                 ComponentArray{a, b, c}),
+                             pos);
     }
 
-    static DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse) {
-        return DSLWriter::IRGenerator().convertTernaryExpression(test.release(), ifTrue.release(),
+    static DSLExpression Swizzle(DSLExpression base,
+                                 SkSL::SwizzleComponent::Type a,
+                                 SkSL::SwizzleComponent::Type b,
+                                 SkSL::SwizzleComponent::Type c,
+                                 SkSL::SwizzleComponent::Type d,
+                                 PositionInfo pos) {
+        return DSLExpression(Swizzle::MakeWith01(DSLWriter::Context(), base.release(),
+                                                 ComponentArray{a,b,c,d}),
+                             pos);
+    }
+
+    static DSLPossibleExpression Select(DSLExpression test, DSLExpression ifTrue,
+                                        DSLExpression ifFalse) {
+        return DSLWriter::IRGenerator().convertTernaryExpression(test.release(),
+                                                                 ifTrue.release(),
                                                                  ifFalse.release());
     }
 
-    static DSLStatement While(DSLExpression test, DSLStatement stmt) {
+    static DSLPossibleStatement While(DSLExpression test, DSLStatement stmt) {
         return ForStatement::MakeWhile(DSLWriter::Context(), /*offset=*/-1, test.release(),
                                        stmt.release(), DSLWriter::SymbolTable());
     }
@@ -168,234 +182,245 @@
     return DSLCore::Continue();
 }
 
-DSLStatement Declare(DSLVar& var, DSLExpression initialValue) {
-    return DSLCore::Declare(var, std::move(initialValue));
+DSLStatement Declare(DSLVar& var, DSLExpression initialValue, PositionInfo pos) {
+    return DSLStatement(DSLCore::Declare(var, std::move(initialValue)), pos);
 }
 
 DSLStatement Discard() {
     return DSLCore::Discard();
 }
 
-DSLStatement Do(DSLStatement stmt, DSLExpression test) {
-    return DSLCore::Do(std::move(stmt), std::move(test));
+DSLStatement Do(DSLStatement stmt, DSLExpression test, PositionInfo pos) {
+    return DSLStatement(DSLCore::Do(std::move(stmt), std::move(test)), pos);
 }
 
 DSLStatement For(DSLStatement initializer, DSLExpression test, DSLExpression next,
-                 DSLStatement stmt) {
-    return DSLCore::For(std::move(initializer), std::move(test), std::move(next), std::move(stmt));
+                 DSLStatement stmt, PositionInfo pos) {
+    return DSLStatement(DSLCore::For(std::move(initializer), std::move(test), std::move(next),
+                                     std::move(stmt)), pos);
 }
 
-DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse) {
-    return DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse));
+DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse, PositionInfo pos) {
+    return DSLStatement(DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse)), pos);
 }
 
-DSLStatement Return(DSLExpression expr) {
-    return DSLCore::Return(std::move(expr));
+DSLStatement Return(DSLExpression expr, PositionInfo pos) {
+    return DSLCore::Return(std::move(expr), pos);
 }
 
-DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse) {
-    return DSLCore::Select(std::move(test), std::move(ifTrue), std::move(ifFalse));
+DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse,
+                     PositionInfo pos) {
+    return DSLExpression(DSLCore::Select(std::move(test), std::move(ifTrue), std::move(ifFalse)),
+                         pos);
 }
 
-DSLStatement While(DSLExpression test, DSLStatement stmt) {
-    return DSLCore::While(std::move(test), std::move(stmt));
+DSLStatement While(DSLExpression test, DSLStatement stmt, PositionInfo pos) {
+    return DSLStatement(DSLCore::While(std::move(test), std::move(stmt)), pos);
 }
 
-DSLExpression Abs(DSLExpression x) {
-    return DSLCore::Call("abs", std::move(x));
+DSLExpression Abs(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("abs", std::move(x)), pos);
 }
 
-DSLExpression All(DSLExpression x) {
-    return DSLCore::Call("all", std::move(x));
+DSLExpression All(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("all", std::move(x)), pos);
 }
 
-DSLExpression Any(DSLExpression x) {
-    return DSLCore::Call("any", std::move(x));
+DSLExpression Any(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("any", std::move(x)), pos);
 }
 
-DSLExpression Ceil(DSLExpression x) {
-    return DSLCore::Call("ceil", std::move(x));
+DSLExpression Ceil(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("ceil", std::move(x)), pos);
 }
 
-DSLExpression Clamp(DSLExpression x, DSLExpression min, DSLExpression max) {
-    return DSLCore::Call("clamp", std::move(x), std::move(min), std::move(max));
+DSLExpression Clamp(DSLExpression x, DSLExpression min, DSLExpression max, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("clamp", std::move(x), std::move(min), std::move(max)), pos);
 }
 
-DSLExpression Cos(DSLExpression x) {
-    return DSLCore::Call("cos", std::move(x));
+DSLExpression Cos(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("cos", std::move(x)), pos);
 }
 
-DSLExpression Cross(DSLExpression x, DSLExpression y) {
-    return DSLCore::Call("cross", std::move(x), std::move(y));
+DSLExpression Cross(DSLExpression x, DSLExpression y, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("cross", std::move(x), std::move(y)), pos);
 }
 
-DSLExpression Degrees(DSLExpression x) {
-    return DSLCore::Call("degrees", std::move(x));
+DSLExpression Degrees(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("degrees", std::move(x)), pos);
 }
 
-DSLExpression Distance(DSLExpression x, DSLExpression y) {
-    return DSLCore::Call("distance", std::move(x), std::move(y));
+DSLExpression Distance(DSLExpression x, DSLExpression y, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("distance", std::move(x), std::move(y)), pos);
 }
 
-DSLExpression Dot(DSLExpression x, DSLExpression y) {
-    return DSLCore::Call("dot", std::move(x), std::move(y));
+DSLExpression Dot(DSLExpression x, DSLExpression y, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("dot", std::move(x), std::move(y)), pos);
 }
 
-DSLExpression Equal(DSLExpression x, DSLExpression y) {
-    return DSLCore::Call("equal", std::move(x), std::move(y));
+DSLExpression Equal(DSLExpression x, DSLExpression y, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("equal", std::move(x), std::move(y)), pos);
 }
 
-DSLExpression Exp(DSLExpression x) {
-    return DSLCore::Call("exp", std::move(x));
+DSLExpression Exp(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("exp", std::move(x)), pos);
 }
 
-DSLExpression Exp2(DSLExpression x) {
-    return DSLCore::Call("exp2", std::move(x));
+DSLExpression Exp2(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("exp2", std::move(x)), pos);
 }
 
-DSLExpression Faceforward(DSLExpression n, DSLExpression i, DSLExpression nref) {
-    return DSLCore::Call("faceforward", std::move(n), std::move(i), std::move(nref));
+DSLExpression Faceforward(DSLExpression n, DSLExpression i, DSLExpression nref, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("faceforward", std::move(n), std::move(i), std::move(nref)),
+                         pos);
 }
 
-DSLExpression Fract(DSLExpression x) {
-    return DSLCore::Call("fract", std::move(x));
+DSLExpression Fract(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("fract", std::move(x)), pos);
 }
 
-DSLExpression Floor(DSLExpression x) {
-    return DSLCore::Call("floor", std::move(x));
+DSLExpression Floor(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("floor", std::move(x)), pos);
 }
 
-DSLExpression GreaterThan(DSLExpression x, DSLExpression y) {
-    return DSLCore::Call("greaterThan", std::move(x), std::move(y));
+DSLExpression GreaterThan(DSLExpression x, DSLExpression y, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("greaterThan", std::move(x), std::move(y)), pos);
 }
 
-DSLExpression GreaterThanEqual(DSLExpression x, DSLExpression y) {
-    return DSLCore::Call("greaterThanEqual", std::move(x), std::move(y));
+DSLExpression GreaterThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("greaterThanEqual", std::move(x), std::move(y)), pos);
 }
 
-DSLExpression Inverse(DSLExpression x) {
-    return DSLCore::Call("inverse", std::move(x));
+DSLExpression Inverse(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("inverse", std::move(x)), pos);
 }
 
-DSLExpression Inversesqrt(DSLExpression x) {
-    return DSLCore::Call("inversesqrt", std::move(x));
+DSLExpression Inversesqrt(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("inversesqrt", std::move(x)), pos);
 }
 
-DSLExpression Length(DSLExpression x) {
-    return DSLCore::Call("length", std::move(x));
+DSLExpression Length(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("length", std::move(x)), pos);
 }
 
-DSLExpression LessThan(DSLExpression x, DSLExpression y) {
-    return DSLCore::Call("lessThan", std::move(x), std::move(y));
+DSLExpression LessThan(DSLExpression x, DSLExpression y, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("lessThan", std::move(x), std::move(y)), pos);
 }
 
-DSLExpression LessThanEqual(DSLExpression x, DSLExpression y) {
-    return DSLCore::Call("lessThanEqual", std::move(x), std::move(y));
+DSLExpression LessThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("lessThanEqual", std::move(x), std::move(y)), pos);
 }
 
-DSLExpression Log(DSLExpression x) {
-    return DSLCore::Call("log", std::move(x));
+DSLExpression Log(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("log", std::move(x)), pos);
 }
 
-DSLExpression Log2(DSLExpression x) {
-    return DSLCore::Call("log2", std::move(x));
+DSLExpression Log2(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("log2", std::move(x)), pos);
 }
 
-DSLExpression Max(DSLExpression x, DSLExpression y) {
-    return DSLCore::Call("max", std::move(x), std::move(y));
+DSLExpression Max(DSLExpression x, DSLExpression y, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("max", std::move(x), std::move(y)), pos);
 }
 
-DSLExpression Min(DSLExpression x, DSLExpression y) {
-    return DSLCore::Call("min", std::move(x), std::move(y));
+DSLExpression Min(DSLExpression x, DSLExpression y, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("min", std::move(x), std::move(y)), pos);
 }
 
-DSLExpression Mix(DSLExpression x, DSLExpression y, DSLExpression a) {
-    return DSLCore::Call("mix", std::move(x), std::move(y), std::move(a));
+DSLExpression Mix(DSLExpression x, DSLExpression y, DSLExpression a, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("mix", std::move(x), std::move(y), std::move(a)), pos);
 }
 
-DSLExpression Mod(DSLExpression x, DSLExpression y) {
-    return DSLCore::Call("mod", std::move(x), std::move(y));
+DSLExpression Mod(DSLExpression x, DSLExpression y, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("mod", std::move(x), std::move(y)), pos);
 }
 
-DSLExpression Normalize(DSLExpression x) {
-    return DSLCore::Call("normalize", std::move(x));
+DSLExpression Normalize(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("normalize", std::move(x)), pos);
 }
 
-DSLExpression NotEqual(DSLExpression x, DSLExpression y) {
-    return DSLCore::Call("notEqual", std::move(x), std::move(y));
+DSLExpression NotEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("notEqual", std::move(x), std::move(y)), pos);
 }
 
-DSLExpression Pow(DSLExpression x, DSLExpression y) {
-    return DSLCore::Call("pow", std::move(x), std::move(y));
+DSLExpression Pow(DSLExpression x, DSLExpression y, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("pow", std::move(x), std::move(y)), pos);
 }
 
-DSLExpression Radians(DSLExpression x) {
-    return DSLCore::Call("radians", std::move(x));
+DSLExpression Radians(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("radians", std::move(x)), pos);
 }
 
-DSLExpression Reflect(DSLExpression i, DSLExpression n) {
-    return DSLCore::Call("reflect", std::move(i), std::move(n));
+DSLExpression Reflect(DSLExpression i, DSLExpression n, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("reflect", std::move(i), std::move(n)), pos);
 }
 
-DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta) {
-    return DSLCore::Call("refract", std::move(i), std::move(n), std::move(eta));
+DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("refract", std::move(i), std::move(n), std::move(eta)), pos);
 }
 
-DSLExpression Saturate(DSLExpression x) {
-    return DSLCore::Call("saturate", std::move(x));
+DSLExpression Saturate(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("saturate", std::move(x)), pos);
 }
 
-DSLExpression Sign(DSLExpression x) {
-    return DSLCore::Call("sign", std::move(x));
+DSLExpression Sign(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("sign", std::move(x)), pos);
 }
 
-DSLExpression Sin(DSLExpression x) {
-    return DSLCore::Call("sin", std::move(x));
+DSLExpression Sin(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("sin", std::move(x)), pos);
 }
 
-DSLExpression Smoothstep(DSLExpression edge1, DSLExpression edge2, DSLExpression x) {
-    return DSLCore::Call("smoothstep", std::move(edge1), std::move(edge2), std::move(x));
+DSLExpression Smoothstep(DSLExpression edge1, DSLExpression edge2, DSLExpression x,
+                         PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("smoothstep", std::move(edge1), std::move(edge2),
+                                       std::move(x)),
+                         pos);
 }
 
-DSLExpression Sqrt(DSLExpression x) {
-    return DSLCore::Call("sqrt", std::move(x));
+DSLExpression Sqrt(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("sqrt", std::move(x)), pos);
 }
 
-DSLExpression Step(DSLExpression edge, DSLExpression x) {
-    return DSLCore::Call("step", std::move(edge), std::move(x));
+DSLExpression Step(DSLExpression edge, DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("step", std::move(edge), std::move(x)), pos);
 }
 
-DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a) {
-    return DSLCore::Swizzle(std::move(base), a);
-}
-
-DSLExpression Swizzle(DSLExpression base,
-                      SkSL::SwizzleComponent::Type a,
-                      SkSL::SwizzleComponent::Type b) {
-    return DSLCore::Swizzle(std::move(base), a, b);
+DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a,
+                      PositionInfo pos) {
+    return DSLCore::Swizzle(std::move(base), a, pos);
 }
 
 DSLExpression Swizzle(DSLExpression base,
                       SkSL::SwizzleComponent::Type a,
                       SkSL::SwizzleComponent::Type b,
-                      SkSL::SwizzleComponent::Type c) {
-    return DSLCore::Swizzle(std::move(base), a, b, c);
+                      PositionInfo pos) {
+    return DSLCore::Swizzle(std::move(base), a, b, pos);
 }
 
 DSLExpression Swizzle(DSLExpression base,
                       SkSL::SwizzleComponent::Type a,
                       SkSL::SwizzleComponent::Type b,
                       SkSL::SwizzleComponent::Type c,
-                      SkSL::SwizzleComponent::Type d) {
-    return DSLCore::Swizzle(std::move(base), a, b, c, d);
+                      PositionInfo pos) {
+    return DSLCore::Swizzle(std::move(base), a, b, c, pos);
 }
 
-DSLExpression Tan(DSLExpression x) {
-    return DSLCore::Call("tan", std::move(x));
+DSLExpression Swizzle(DSLExpression base,
+                      SkSL::SwizzleComponent::Type a,
+                      SkSL::SwizzleComponent::Type b,
+                      SkSL::SwizzleComponent::Type c,
+                      SkSL::SwizzleComponent::Type d,
+                      PositionInfo pos) {
+    return DSLCore::Swizzle(std::move(base), a, b, c, d, pos);
 }
 
-DSLExpression Unpremul(DSLExpression x) {
-    return DSLCore::Call("unpremul", std::move(x));
+DSLExpression Tan(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("tan", std::move(x)), pos);
+}
+
+DSLExpression Unpremul(DSLExpression x, PositionInfo pos) {
+    return DSLExpression(DSLCore::Call("unpremul", std::move(x)), pos);
 }
 
 } // namespace dsl
diff --git a/src/sksl/dsl/DSLCore.h b/src/sksl/dsl/DSLCore.h
index e97fb4f..1f80c04 100644
--- a/src/sksl/dsl/DSLCore.h
+++ b/src/sksl/dsl/DSLCore.h
@@ -12,6 +12,7 @@
 #include "src/sksl/SkSLDefines.h"
 #include "src/sksl/dsl/DSLBlock.h"
 #include "src/sksl/dsl/DSLCase.h"
+#include "src/sksl/dsl/DSLErrorHandling.h"
 #include "src/sksl/dsl/DSLExpression.h"
 #include "src/sksl/dsl/DSLFunction.h"
 #include "src/sksl/dsl/DSLStatement.h"
@@ -66,7 +67,8 @@
 /**
  * Creates a variable declaration statement with an initial value.
  */
-DSLStatement Declare(DSLVar& var, DSLExpression initialValue = DSLExpression());
+DSLStatement Declare(DSLVar& var, DSLExpression initialValue = DSLExpression(),
+                     PositionInfo pos = PositionInfo());
 
 /**
  * default: statements
@@ -84,29 +86,36 @@
 /**
  * do stmt; while (test);
  */
-DSLStatement Do(DSLStatement stmt, DSLExpression test);
+DSLStatement Do(DSLStatement stmt, DSLExpression test, PositionInfo pos = PositionInfo());
 
 /**
  * for (initializer; test; next) stmt;
  */
 DSLStatement For(DSLStatement initializer, DSLExpression test, DSLExpression next,
-                 DSLStatement stmt);
+                 DSLStatement stmt, PositionInfo pos = PositionInfo());
 
 /**
  * if (test) ifTrue; [else ifFalse;]
  */
-DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse = DSLStatement());
+DSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse = DSLStatement(),
+                PositionInfo pos = PositionInfo());
 
 /**
  * return [value];
  */
-DSLStatement Return(DSLExpression value = DSLExpression());
+DSLStatement Return(DSLExpression value = DSLExpression(), PositionInfo pos = PositionInfo());
+
+/**
+ * test ? ifTrue : ifFalse
+ */
+DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse,
+                     PositionInfo info = PositionInfo());
 
 /**
  * switch (value) { cases }
  */
 template<class... Cases>
-DSLStatement Switch(DSLExpression value, Cases... cases) {
+DSLPossibleStatement Switch(DSLExpression value, Cases... cases) {
     SkSL::ExpressionArray caseValues;
     SkTArray<StatementArray> caseStatements;
     caseValues.reserve_back(sizeof...(cases));
@@ -120,265 +129,270 @@
 }
 
 /**
- * test ? ifTrue : ifFalse
- */
-DSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse);
-
-/**
  * while (test) stmt;
  */
-DSLStatement While(DSLExpression test, DSLStatement stmt);
+DSLStatement While(DSLExpression test, DSLStatement stmt, PositionInfo info = PositionInfo());
 
 /**
  * expression.xyz1
  */
-DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a);
-
 DSLExpression Swizzle(DSLExpression base,
                       SkSL::SwizzleComponent::Type a,
-                      SkSL::SwizzleComponent::Type b);
+                      PositionInfo pos = PositionInfo());
 
 DSLExpression Swizzle(DSLExpression base,
                       SkSL::SwizzleComponent::Type a,
                       SkSL::SwizzleComponent::Type b,
-                      SkSL::SwizzleComponent::Type c);
+                      PositionInfo pos = PositionInfo());
 
 DSLExpression Swizzle(DSLExpression base,
                       SkSL::SwizzleComponent::Type a,
                       SkSL::SwizzleComponent::Type b,
                       SkSL::SwizzleComponent::Type c,
-                      SkSL::SwizzleComponent::Type d);
+                      PositionInfo pos = PositionInfo());
+
+DSLExpression Swizzle(DSLExpression base,
+                      SkSL::SwizzleComponent::Type a,
+                      SkSL::SwizzleComponent::Type b,
+                      SkSL::SwizzleComponent::Type c,
+                      SkSL::SwizzleComponent::Type d,
+                      PositionInfo pos = PositionInfo());
 
 /**
  * Returns the absolute value of x. If x is a vector, operates componentwise.
  */
-DSLExpression Abs(DSLExpression x);
+DSLExpression Abs(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns true if all of the components of boolean vector x are true.
  */
-DSLExpression All(DSLExpression x);
+DSLExpression All(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns true if any of the components of boolean vector x are true.
  */
-DSLExpression Any(DSLExpression x);
+DSLExpression Any(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns x rounded towards positive infinity. If x is a vector, operates componentwise.
  */
-DSLExpression Ceil(DSLExpression x);
+DSLExpression Ceil(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns x clamped to between min and max. If x is a vector, operates componentwise.
  */
-DSLExpression Clamp(DSLExpression x, DSLExpression min, DSLExpression max);
+DSLExpression Clamp(DSLExpression x, DSLExpression min, DSLExpression max,
+                    PositionInfo pos = PositionInfo());
 
 /**
  * Returns the cosine of x. If x is a vector, operates componentwise.
  */
-DSLExpression Cos(DSLExpression x);
+DSLExpression Cos(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the cross product of x and y.
  */
-DSLExpression Cross(DSLExpression x, DSLExpression y);
+DSLExpression Cross(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
 
 /**
  * Returns x converted from radians to degrees. If x is a vector, operates componentwise.
  */
-DSLExpression Degrees(DSLExpression x);
+DSLExpression Degrees(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the distance between x and y.
  */
-DSLExpression Distance(DSLExpression x, DSLExpression y);
+DSLExpression Distance(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the dot product of x and y.
  */
-DSLExpression Dot(DSLExpression x, DSLExpression y);
+DSLExpression Dot(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
 
 /**
  * Returns a boolean vector indicating whether components of x are equal to the corresponding
  * components of y.
  */
-DSLExpression Equal(DSLExpression x, DSLExpression y);
+DSLExpression Equal(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
 
 /**
  * Returns e^x. If x is a vector, operates componentwise.
  */
-DSLExpression Exp(DSLExpression x);
+DSLExpression Exp(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns 2^x. If x is a vector, operates componentwise.
  */
-DSLExpression Exp2(DSLExpression x);
+DSLExpression Exp2(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * If dot(i, nref) >= 0, returns n, otherwise returns -n.
  */
-DSLExpression Faceforward(DSLExpression n, DSLExpression i, DSLExpression nref);
+DSLExpression Faceforward(DSLExpression n, DSLExpression i, DSLExpression nref,
+                          PositionInfo pos = PositionInfo());
 
 /**
  * Returns x rounded towards negative infinity. If x is a vector, operates componentwise.
  */
-DSLExpression Floor(DSLExpression x);
+DSLExpression Floor(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the fractional part of x. If x is a vector, operates componentwise.
  */
-DSLExpression Fract(DSLExpression x);
+DSLExpression Fract(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns a boolean vector indicating whether components of x are greater than the corresponding
  * components of y.
  */
-DSLExpression GreaterThan(DSLExpression x, DSLExpression y);
+DSLExpression GreaterThan(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
 
 /**
  * Returns a boolean vector indicating whether components of x are greater than or equal to the
  * corresponding components of y.
  */
-DSLExpression GreaterThanEqual(DSLExpression x, DSLExpression y);
+DSLExpression GreaterThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the 1/sqrt(x). If x is a vector, operates componentwise.
  */
-DSLExpression Inversesqrt(DSLExpression x);
+DSLExpression Inversesqrt(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the inverse of the matrix x.
  */
-DSLExpression Inverse(DSLExpression x);
+DSLExpression Inverse(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the length of the vector x.
  */
-DSLExpression Length(DSLExpression x);
+DSLExpression Length(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns a boolean vector indicating whether components of x are less than the corresponding
  * components of y.
  */
-DSLExpression LessThan(DSLExpression x, DSLExpression y);
+DSLExpression LessThan(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
 
 /**
  * Returns a boolean vector indicating whether components of x are less than or equal to the
  * corresponding components of y.
  */
-DSLExpression LessThanEqual(DSLExpression x, DSLExpression y);
+DSLExpression LessThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the log base e of x. If x is a vector, operates componentwise.
  */
-DSLExpression Log(DSLExpression x);
+DSLExpression Log(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the log base 2 of x. If x is a vector, operates componentwise.
  */
-DSLExpression Log2(DSLExpression x);
+DSLExpression Log2(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the larger (closer to positive infinity) of x and y. If x is a vector, operates
  * componentwise. y may be either a vector of the same dimensions as x, or a scalar.
  */
-DSLExpression Max(DSLExpression x, DSLExpression y);
+DSLExpression Max(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the smaller (closer to negative infinity) of x and y. If x is a vector, operates
  * componentwise. y may be either a vector of the same dimensions as x, or a scalar.
  */
-DSLExpression Min(DSLExpression x, DSLExpression y);
+DSLExpression Min(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
 
 /**
  * Returns a linear intepolation between x and y at position a, where a=0 results in x and a=1
  * results in y. If x and y are vectors, operates componentwise. a may be either a vector of the
  * same dimensions as x and y, or a scalar.
  */
-DSLExpression Mix(DSLExpression x, DSLExpression y, DSLExpression a);
+DSLExpression Mix(DSLExpression x, DSLExpression y, DSLExpression a,
+                  PositionInfo pos = PositionInfo());
 
 /**
  * Returns x modulo y. If x is a vector, operates componentwise. y may be either a vector of the
  * same dimensions as x, or a scalar.
  */
-DSLExpression Mod(DSLExpression x, DSLExpression y);
+DSLExpression Mod(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the vector x normalized to a length of 1.
  */
-DSLExpression Normalize(DSLExpression x);
+DSLExpression Normalize(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns a boolean vector indicating whether components of x are not equal to the corresponding
  * components of y.
  */
-DSLExpression NotEqual(DSLExpression x, DSLExpression y);
+DSLExpression NotEqual(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
 
 /**
  * Returns x raised to the power y. If x is a vector, operates componentwise. y may be either a
  * vector of the same dimensions as x, or a scalar.
  */
-DSLExpression Pow(DSLExpression x, DSLExpression y);
+DSLExpression Pow(DSLExpression x, DSLExpression y, PositionInfo pos = PositionInfo());
 
 /**
  * Returns x converted from degrees to radians. If x is a vector, operates componentwise.
  */
-DSLExpression Radians(DSLExpression x);
+DSLExpression Radians(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns i reflected from a surface with normal n.
  */
-DSLExpression Reflect(DSLExpression i, DSLExpression n);
+DSLExpression Reflect(DSLExpression i, DSLExpression n, PositionInfo pos = PositionInfo());
 
 /**
  * Returns i refracted across a surface with normal n and ratio of indices of refraction eta.
  */
-DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta);
+DSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta,
+                      PositionInfo pos = PositionInfo());
 
 /**
  * Returns x clamped to the range [0, 1]. If x is a vector, operates componentwise.
  */
-DSLExpression Saturate(DSLExpression x);
+DSLExpression Saturate(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns -1, 0, or 1 depending on whether x is negative, zero, or positive, respectively. If x is
  * a vector, operates componentwise.
  */
-DSLExpression Sign(DSLExpression x);
+DSLExpression Sign(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the sine of x. If x is a vector, operates componentwise.
  */
-DSLExpression Sin(DSLExpression x);
+DSLExpression Sin(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns a smooth interpolation between 0 (at x=edge1) and 1 (at x=edge2). If x is a vector,
  * operates componentwise. edge1 and edge2 may either be both vectors of the same dimensions as x or
  * scalars.
  */
-DSLExpression Smoothstep(DSLExpression edge1, DSLExpression edge2, DSLExpression x);
+DSLExpression Smoothstep(DSLExpression edge1, DSLExpression edge2, DSLExpression x,
+                         PositionInfo pos = PositionInfo());
 
 /**
  * Returns the square root of x. If x is a vector, operates componentwise.
  */
-DSLExpression Sqrt(DSLExpression x);
+DSLExpression Sqrt(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns 0 if x < edge or 1 if x >= edge. If x is a vector, operates componentwise. edge may be
  * either a vector of the same dimensions as x, or a scalar.
  */
-DSLExpression Step(DSLExpression edge, DSLExpression x);
+DSLExpression Step(DSLExpression edge, DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns the tangent of x. If x is a vector, operates componentwise.
  */
-DSLExpression Tan(DSLExpression x);
+DSLExpression Tan(DSLExpression x, PositionInfo pos = PositionInfo());
 
 /**
  * Returns x converted from premultipled to unpremultiplied alpha.
  */
-DSLExpression Unpremul(DSLExpression x);
+DSLExpression Unpremul(DSLExpression x, PositionInfo pos = PositionInfo());
 
 } // namespace dsl
 
diff --git a/src/sksl/dsl/DSLExpression.cpp b/src/sksl/dsl/DSLExpression.cpp
index 5f7cb74..bf16666 100644
--- a/src/sksl/dsl/DSLExpression.cpp
+++ b/src/sksl/dsl/DSLExpression.cpp
@@ -90,62 +90,62 @@
     return std::move(fExpression);
 }
 
-DSLExpression DSLExpression::x() {
-    return Swizzle(this->release(), X);
+DSLExpression DSLExpression::x(PositionInfo pos) {
+    return Swizzle(this->release(), X, pos);
 }
 
-DSLExpression DSLExpression::y() {
-    return Swizzle(this->release(), Y);
+DSLExpression DSLExpression::y(PositionInfo pos) {
+    return Swizzle(this->release(), Y, pos);
 }
 
-DSLExpression DSLExpression::z() {
-    return Swizzle(this->release(), Z);
+DSLExpression DSLExpression::z(PositionInfo pos) {
+    return Swizzle(this->release(), Z, pos);
 }
 
-DSLExpression DSLExpression::w() {
-    return Swizzle(this->release(), W);
+DSLExpression DSLExpression::w(PositionInfo pos) {
+    return Swizzle(this->release(), W, pos);
 }
 
-DSLExpression DSLExpression::r() {
-    return Swizzle(this->release(), R);
+DSLExpression DSLExpression::r(PositionInfo pos) {
+    return Swizzle(this->release(), R, pos);
 }
 
-DSLExpression DSLExpression::g() {
-    return Swizzle(this->release(), G);
+DSLExpression DSLExpression::g(PositionInfo pos) {
+    return Swizzle(this->release(), G, pos);
 }
 
-DSLExpression DSLExpression::b() {
-    return Swizzle(this->release(), B);
+DSLExpression DSLExpression::b(PositionInfo pos) {
+    return Swizzle(this->release(), B, pos);
 }
 
-DSLExpression DSLExpression::a() {
-    return Swizzle(this->release(), A);
+DSLExpression DSLExpression::a(PositionInfo pos) {
+    return Swizzle(this->release(), A, pos);
 }
 
-DSLExpression DSLExpression::field(const char* name) {
-    return DSLWriter::ConvertField(this->release(), name);
+DSLExpression DSLExpression::field(const char* name, PositionInfo pos) {
+    return DSLExpression(DSLWriter::ConvertField(this->release(), name), pos);
 }
 
-DSLExpression DSLExpression::operator=(DSLExpression right) {
+DSLPossibleExpression DSLExpression::operator=(DSLExpression right) {
     return DSLWriter::ConvertBinary(this->release(), SkSL::Token::Kind::TK_EQ, right.release());
 }
 
-DSLExpression DSLExpression::operator[](DSLExpression right) {
+DSLPossibleExpression DSLExpression::operator[](DSLExpression right) {
     return DSLWriter::ConvertIndex(this->release(), right.release());
 }
 
 #define OP(op, token)                                                                              \
-DSLExpression operator op(DSLExpression left, DSLExpression right) {                               \
+DSLPossibleExpression operator op(DSLExpression left, DSLExpression right) {                       \
     return DSLWriter::ConvertBinary(left.release(), SkSL::Token::Kind::token, right.release());    \
 }
 
 #define PREFIXOP(op, token)                                                                        \
-DSLExpression operator op(DSLExpression expr) {                                                    \
+DSLPossibleExpression operator op(DSLExpression expr) {                                            \
     return DSLWriter::ConvertPrefix(SkSL::Token::Kind::token, expr.release());                     \
 }
 
 #define POSTFIXOP(op, token)                                                                       \
-DSLExpression operator op(DSLExpression expr, int) {                                               \
+DSLPossibleExpression operator op(DSLExpression expr, int) {                                       \
     return DSLWriter::ConvertPostfix(expr.release(), SkSL::Token::Kind::token);                    \
 }
 
@@ -185,8 +185,9 @@
 PREFIXOP(--, TK_MINUSMINUS)
 POSTFIXOP(--, TK_MINUSMINUS)
 
-DSLExpression operator,(DSLExpression left, DSLExpression right) {
-    return DSLWriter::ConvertBinary(left.release(), SkSL::Token::Kind::TK_COMMA, right.release());
+DSLPossibleExpression operator,(DSLExpression left, DSLExpression right) {
+    return DSLWriter::ConvertBinary(left.release(), SkSL::Token::Kind::TK_COMMA,
+                                    right.release());
 }
 
 std::unique_ptr<SkSL::Expression> DSLExpression::coerceAndRelease(const SkSL::Type& type) {
@@ -208,74 +209,74 @@
 }
 
 DSLExpression DSLPossibleExpression::x(PositionInfo pos) {
-    return DSLExpression(this->release()).x();
+    return DSLExpression(this->release()).x(pos);
 }
 
 DSLExpression DSLPossibleExpression::y(PositionInfo pos) {
-    return DSLExpression(this->release()).y();
+    return DSLExpression(this->release()).y(pos);
 }
 
 DSLExpression DSLPossibleExpression::z(PositionInfo pos) {
-    return DSLExpression(this->release()).z();
+    return DSLExpression(this->release()).z(pos);
 }
 
 DSLExpression DSLPossibleExpression::w(PositionInfo pos) {
-    return DSLExpression(this->release()).w();
+    return DSLExpression(this->release()).w(pos);
 }
 
 DSLExpression DSLPossibleExpression::r(PositionInfo pos) {
-    return DSLExpression(this->release()).r();
+    return DSLExpression(this->release()).r(pos);
 }
 
 DSLExpression DSLPossibleExpression::g(PositionInfo pos) {
-    return DSLExpression(this->release()).g();
+    return DSLExpression(this->release()).g(pos);
 }
 
 DSLExpression DSLPossibleExpression::b(PositionInfo pos) {
-    return DSLExpression(this->release()).b();
+    return DSLExpression(this->release()).b(pos);
 }
 
 DSLExpression DSLPossibleExpression::a(PositionInfo pos) {
-    return DSLExpression(this->release()).a();
+    return DSLExpression(this->release()).a(pos);
 }
 
 DSLExpression DSLPossibleExpression::field(const char* name, PositionInfo pos) {
-    return DSLExpression(this->release()).field(name);
+    return DSLExpression(this->release()).field(name, pos);
 }
 
-DSLExpression DSLPossibleExpression::operator=(const DSLVar& var) {
+DSLPossibleExpression DSLPossibleExpression::operator=(const DSLVar& var) {
     return this->operator=(DSLExpression(var));
 }
 
-DSLExpression DSLPossibleExpression::operator=(DSLExpression expr) {
+DSLPossibleExpression DSLPossibleExpression::operator=(DSLExpression expr) {
     return DSLExpression(this->release()) = std::move(expr);
 }
 
-DSLExpression DSLPossibleExpression::operator=(int expr) {
+DSLPossibleExpression DSLPossibleExpression::operator=(int expr) {
     return this->operator=(DSLExpression(expr));
 }
 
-DSLExpression DSLPossibleExpression::operator=(float expr) {
+DSLPossibleExpression DSLPossibleExpression::operator=(float expr) {
     return this->operator=(DSLExpression(expr));
 }
 
-DSLExpression DSLPossibleExpression::operator[](DSLExpression index) {
+DSLPossibleExpression DSLPossibleExpression::operator[](DSLExpression index) {
     return DSLExpression(this->release())[std::move(index)];
 }
 
-DSLExpression DSLPossibleExpression::operator++() {
+DSLPossibleExpression DSLPossibleExpression::operator++() {
     return ++DSLExpression(this->release());
 }
 
-DSLExpression DSLPossibleExpression::operator++(int) {
+DSLPossibleExpression DSLPossibleExpression::operator++(int) {
     return DSLExpression(this->release())++;
 }
 
-DSLExpression DSLPossibleExpression::operator--() {
+DSLPossibleExpression DSLPossibleExpression::operator--() {
     return --DSLExpression(this->release());
 }
 
-DSLExpression DSLPossibleExpression::operator--(int) {
+DSLPossibleExpression DSLPossibleExpression::operator--(int) {
     return DSLExpression(this->release())--;
 }
 
diff --git a/src/sksl/dsl/DSLExpression.h b/src/sksl/dsl/DSLExpression.h
index 4cc0b89..4893be0 100644
--- a/src/sksl/dsl/DSLExpression.h
+++ b/src/sksl/dsl/DSLExpression.h
@@ -69,33 +69,33 @@
     /**
      * Overloads the '=' operator to create an SkSL assignment statement.
      */
-    DSLExpression operator=(DSLExpression other);
+    DSLPossibleExpression operator=(DSLExpression other);
 
-    DSLExpression x();
+    DSLExpression x(PositionInfo pos = PositionInfo());
 
-    DSLExpression y();
+    DSLExpression y(PositionInfo pos = PositionInfo());
 
-    DSLExpression z();
+    DSLExpression z(PositionInfo pos = PositionInfo());
 
-    DSLExpression w();
+    DSLExpression w(PositionInfo pos = PositionInfo());
 
-    DSLExpression r();
+    DSLExpression r(PositionInfo pos = PositionInfo());
 
-    DSLExpression g();
+    DSLExpression g(PositionInfo pos = PositionInfo());
 
-    DSLExpression b();
+    DSLExpression b(PositionInfo pos = PositionInfo());
 
-    DSLExpression a();
+    DSLExpression a(PositionInfo pos = PositionInfo());
 
     /**
      * Creates an SkSL struct field access expression.
      */
-    DSLExpression field(const char* name);
+    DSLExpression field(const char* name, PositionInfo pos = PositionInfo());
 
     /**
      * Creates an SkSL array index expression.
      */
-    DSLExpression operator[](DSLExpression index);
+    DSLPossibleExpression operator[](DSLExpression index);
 
     /**
      * Invalidates this object and returns the SkSL expression it represents.
@@ -115,9 +115,6 @@
 
     friend DSLExpression SampleChild(int index, DSLExpression coords);
 
-    template<class... Cases>
-    friend DSLStatement Switch(DSLExpression value, Cases... cases);
-
     friend class DSLCore;
     friend class DSLFunction;
     friend class DSLPossibleExpression;
@@ -125,41 +122,41 @@
     friend class DSLWriter;
 };
 
-DSLExpression operator+(DSLExpression left, DSLExpression right);
-DSLExpression operator+=(DSLExpression left, DSLExpression right);
-DSLExpression operator-(DSLExpression left, DSLExpression right);
-DSLExpression operator-=(DSLExpression left, DSLExpression right);
-DSLExpression operator*(DSLExpression left, DSLExpression right);
-DSLExpression operator*=(DSLExpression left, DSLExpression right);
-DSLExpression operator/(DSLExpression left, DSLExpression right);
-DSLExpression operator/=(DSLExpression left, DSLExpression right);
-DSLExpression operator%(DSLExpression left, DSLExpression right);
-DSLExpression operator%=(DSLExpression left, DSLExpression right);
-DSLExpression operator<<(DSLExpression left, DSLExpression right);
-DSLExpression operator<<=(DSLExpression left, DSLExpression right);
-DSLExpression operator>>(DSLExpression left, DSLExpression right);
-DSLExpression operator>>=(DSLExpression left, DSLExpression right);
-DSLExpression operator&&(DSLExpression left, DSLExpression right);
-DSLExpression operator||(DSLExpression left, DSLExpression right);
-DSLExpression operator&(DSLExpression left, DSLExpression right);
-DSLExpression operator&=(DSLExpression left, DSLExpression right);
-DSLExpression operator|(DSLExpression left, DSLExpression right);
-DSLExpression operator|=(DSLExpression left, DSLExpression right);
-DSLExpression operator^(DSLExpression left, DSLExpression right);
-DSLExpression operator^=(DSLExpression left, DSLExpression right);
-DSLExpression operator,(DSLExpression left, DSLExpression right);
-DSLExpression operator==(DSLExpression left, DSLExpression right);
-DSLExpression operator!=(DSLExpression left, DSLExpression right);
-DSLExpression operator>(DSLExpression left, DSLExpression right);
-DSLExpression operator<(DSLExpression left, DSLExpression right);
-DSLExpression operator>=(DSLExpression left, DSLExpression right);
-DSLExpression operator<=(DSLExpression left, DSLExpression right);
-DSLExpression operator!(DSLExpression expr);
-DSLExpression operator~(DSLExpression expr);
-DSLExpression operator++(DSLExpression expr);
-DSLExpression operator++(DSLExpression expr, int);
-DSLExpression operator--(DSLExpression expr);
-DSLExpression operator--(DSLExpression expr, int);
+DSLPossibleExpression operator+(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator+=(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator-(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator-=(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator*(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator*=(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator/(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator/=(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator%(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator%=(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator<<(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator<<=(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator>>(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator>>=(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator&&(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator||(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator&(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator&=(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator|(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator|=(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator^(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator^=(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator,(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator==(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator!=(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator>(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator<(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator>=(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator<=(DSLExpression left, DSLExpression right);
+DSLPossibleExpression operator!(DSLExpression expr);
+DSLPossibleExpression operator~(DSLExpression expr);
+DSLPossibleExpression operator++(DSLExpression expr);
+DSLPossibleExpression operator++(DSLExpression expr, int);
+DSLPossibleExpression operator--(DSLExpression expr);
+DSLPossibleExpression operator--(DSLExpression expr, int);
 
 /**
  * Represents an Expression which may have failed and/or have pending errors to report. Converting a
@@ -196,23 +193,23 @@
 
     DSLExpression field(const char* name, PositionInfo pos = PositionInfo());
 
-    DSLExpression operator=(const DSLVar& var);
+    DSLPossibleExpression operator=(const DSLVar& var);
 
-    DSLExpression operator=(DSLExpression expr);
+    DSLPossibleExpression operator=(DSLExpression expr);
 
-    DSLExpression operator=(int expr);
+    DSLPossibleExpression operator=(int expr);
 
-    DSLExpression operator=(float expr);
+    DSLPossibleExpression operator=(float expr);
 
-    DSLExpression operator[](DSLExpression index);
+    DSLPossibleExpression operator[](DSLExpression index);
 
-    DSLExpression operator++();
+    DSLPossibleExpression operator++();
 
-    DSLExpression operator++(int);
+    DSLPossibleExpression operator++(int);
 
-    DSLExpression operator--();
+    DSLPossibleExpression operator--();
 
-    DSLExpression operator--(int);
+    DSLPossibleExpression operator--(int);
 
     std::unique_ptr<SkSL::Expression> release();
 
diff --git a/src/sksl/dsl/DSLVar.cpp b/src/sksl/dsl/DSLVar.cpp
index 52466e5..3272a87 100644
--- a/src/sksl/dsl/DSLVar.cpp
+++ b/src/sksl/dsl/DSLVar.cpp
@@ -101,11 +101,11 @@
 }
 #endif
 
-DSLExpression DSLVar::operator[](DSLExpression&& index) {
+DSLPossibleExpression DSLVar::operator[](DSLExpression&& index) {
     return DSLExpression(*this)[std::move(index)];
 }
 
-DSLExpression DSLVar::operator=(DSLExpression expr) {
+DSLPossibleExpression DSLVar::operator=(DSLExpression expr) {
     return DSLWriter::ConvertBinary(DSLExpression(*this).release(), SkSL::Token::Kind::TK_EQ,
                                     expr.release());
 }
diff --git a/src/sksl/dsl/DSLVar.h b/src/sksl/dsl/DSLVar.h
index 7587fb2..b1aaa37 100644
--- a/src/sksl/dsl/DSLVar.h
+++ b/src/sksl/dsl/DSLVar.h
@@ -70,30 +70,38 @@
         return DSLExpression(*this).field(name);
     }
 
-    DSLExpression operator=(const DSLVar& var) {
+    DSLPossibleExpression operator=(const DSLVar& var) {
         return this->operator=(DSLExpression(var));
     }
 
-    DSLExpression operator=(DSLExpression expr);
+    DSLPossibleExpression operator=(DSLExpression expr);
 
-    DSLExpression operator=(int expr) {
+    DSLPossibleExpression operator=(int expr) {
         return this->operator=(DSLExpression(expr));
     }
 
-    DSLExpression operator=(float expr) {
+    DSLPossibleExpression operator=(float expr) {
         return this->operator=(DSLExpression(expr));
     }
 
-    DSLExpression operator[](DSLExpression&& index);
+    DSLPossibleExpression operator[](DSLExpression&& index);
 
-    DSLExpression operator++() {
+    DSLPossibleExpression operator++() {
         return ++DSLExpression(*this);
     }
 
-    DSLExpression operator++(int) {
+    DSLPossibleExpression operator++(int) {
         return DSLExpression(*this)++;
     }
 
+    DSLPossibleExpression operator--() {
+        return --DSLExpression(*this);
+    }
+
+    DSLPossibleExpression operator--(int) {
+        return DSLExpression(*this)--;
+    }
+
 private:
     /**
      * Constructs a reference to a variable that already exists in the symbol table. This is used
diff --git a/src/sksl/dsl/priv/DSLWriter.cpp b/src/sksl/dsl/priv/DSLWriter.cpp
index 66f7079..62307b7 100644
--- a/src/sksl/dsl/priv/DSLWriter.cpp
+++ b/src/sksl/dsl/priv/DSLWriter.cpp
@@ -14,6 +14,7 @@
 #include "src/sksl/SkSLDefines.h"
 #include "src/sksl/SkSLIRGenerator.h"
 #include "src/sksl/dsl/DSLCore.h"
+#include "src/sksl/dsl/DSLErrorHandling.h"
 #include "src/sksl/ir/SkSLConstructor.h"
 #include "src/sksl/ir/SkSLSwitchStatement.h"
 
@@ -97,45 +98,50 @@
     return expr;
 }
 
-DSLExpression DSLWriter::Coerce(std::unique_ptr<Expression> left, const SkSL::Type& type) {
-    return DSLExpression(Check(IRGenerator().coerce(std::move(left), type)));
+DSLPossibleExpression DSLWriter::Coerce(std::unique_ptr<Expression> left, const SkSL::Type& type) {
+    return IRGenerator().coerce(std::move(left), type);
 }
 
-DSLExpression DSLWriter::Construct(const SkSL::Type& type, std::vector<DSLExpression> rawArgs) {
+DSLPossibleExpression DSLWriter::Construct(const SkSL::Type& type,
+                                           std::vector<DSLExpression> rawArgs) {
     SkSL::ExpressionArray args;
     args.reserve_back(rawArgs.size());
 
     for (DSLExpression& arg : rawArgs) {
         args.push_back(arg.release());
     }
-    return DSLExpression(SkSL::Constructor::Make(Context(), /*offset=*/-1, type, std::move(args)));
+    return SkSL::Constructor::Make(Context(), /*offset=*/-1, type, std::move(args));
 }
 
-DSLExpression DSLWriter::ConvertBinary(std::unique_ptr<Expression> left, Operator op,
-                                       std::unique_ptr<Expression> right) {
+std::unique_ptr<SkSL::Expression> DSLWriter::ConvertBinary(std::unique_ptr<Expression> left,
+                                                           Operator op,
+                                                           std::unique_ptr<Expression> right) {
     return IRGenerator().convertBinaryExpression(std::move(left), op, std::move(right));
 }
 
-DSLExpression DSLWriter::ConvertField(std::unique_ptr<Expression> base, const char* name) {
+std::unique_ptr<SkSL::Expression> DSLWriter::ConvertField(std::unique_ptr<Expression> base,
+                                                          const char* name) {
     return IRGenerator().convertField(std::move(base), name);
 }
 
-DSLExpression DSLWriter::ConvertIndex(std::unique_ptr<Expression> base,
-                                      std::unique_ptr<Expression> index) {
+std::unique_ptr<SkSL::Expression> DSLWriter::ConvertIndex(std::unique_ptr<Expression> base,
+                                                          std::unique_ptr<Expression> index) {
     return IRGenerator().convertIndex(std::move(base), std::move(index));
 }
 
-DSLExpression DSLWriter::ConvertPostfix(std::unique_ptr<Expression> expr, Operator op) {
+std::unique_ptr<SkSL::Expression> DSLWriter::ConvertPostfix(std::unique_ptr<Expression> expr,
+                                                            Operator op) {
     return IRGenerator().convertPostfixExpression(std::move(expr), op);
 }
 
-DSLExpression DSLWriter::ConvertPrefix(Operator op, std::unique_ptr<Expression> expr) {
+std::unique_ptr<SkSL::Expression> DSLWriter::ConvertPrefix(Operator op,
+                                                           std::unique_ptr<Expression> expr) {
     return IRGenerator().convertPrefixExpression(op, std::move(expr));
 }
 
-DSLStatement DSLWriter::ConvertSwitch(std::unique_ptr<Expression> value,
-                                      ExpressionArray caseValues,
-                                      SkTArray<SkSL::StatementArray> caseStatements) {
+DSLPossibleStatement DSLWriter::ConvertSwitch(std::unique_ptr<Expression> value,
+                                              ExpressionArray caseValues,
+                                              SkTArray<SkSL::StatementArray> caseStatements) {
     return SwitchStatement::Make(Context(), /*offset=*/-1, /*isStatic=*/false, std::move(value),
                                  std::move(caseValues), std::move(caseStatements),
                                  IRGenerator().fSymbolTable);
diff --git a/src/sksl/dsl/priv/DSLWriter.h b/src/sksl/dsl/priv/DSLWriter.h
index 8a46b85..7f3f988 100644
--- a/src/sksl/dsl/priv/DSLWriter.h
+++ b/src/sksl/dsl/priv/DSLWriter.h
@@ -132,25 +132,28 @@
      */
     static std::unique_ptr<SkSL::Expression> Check(std::unique_ptr<SkSL::Expression> expr);
 
-    static DSLExpression Coerce(std::unique_ptr<Expression> left, const SkSL::Type& type);
+    static DSLPossibleExpression Coerce(std::unique_ptr<Expression> left, const SkSL::Type& type);
 
-    static DSLExpression Construct(const SkSL::Type& type, std::vector<DSLExpression> rawArgs);
+    static DSLPossibleExpression Construct(const SkSL::Type& type,
+                                           std::vector<DSLExpression> rawArgs);
 
-    static DSLExpression ConvertBinary(std::unique_ptr<Expression> left, Operator op,
-                                       std::unique_ptr<Expression> right);
+    static std::unique_ptr<Expression> ConvertBinary(std::unique_ptr<Expression> left, Operator op,
+                                                     std::unique_ptr<Expression> right);
 
-    static DSLExpression ConvertField(std::unique_ptr<Expression> base, const char* name);
+    static std::unique_ptr<SkSL::Expression> ConvertField(std::unique_ptr<Expression> base,
+                                                          const char* name);
 
-    static DSLExpression ConvertIndex(std::unique_ptr<Expression> base,
-                                      std::unique_ptr<Expression> index);
+    static std::unique_ptr<Expression> ConvertIndex(std::unique_ptr<Expression> base,
+                                                    std::unique_ptr<Expression> index);
 
-    static DSLExpression ConvertPostfix(std::unique_ptr<Expression> expr, Operator op);
+    static std::unique_ptr<Expression> ConvertPostfix(std::unique_ptr<Expression> expr,
+                                                      Operator op);
 
-    static DSLExpression ConvertPrefix(Operator op, std::unique_ptr<Expression> expr);
+    static std::unique_ptr<Expression> ConvertPrefix(Operator op, std::unique_ptr<Expression> expr);
 
-    static DSLStatement ConvertSwitch(std::unique_ptr<Expression> value,
-                                      ExpressionArray caseValues,
-                                      SkTArray<SkSL::StatementArray> caseStatements);
+    static DSLPossibleStatement ConvertSwitch(std::unique_ptr<Expression> value,
+                                              ExpressionArray caseValues,
+                                              SkTArray<SkSL::StatementArray> caseStatements);
 
     static void Ignore(std::unique_ptr<SkSL::Expression>&) {}
 
diff --git a/tests/SkSLDSLErrorLineNumbers.cpp b/tests/SkSLDSLErrorLineNumbers.cpp
new file mode 100644
index 0000000..66a32a3
--- /dev/null
+++ b/tests/SkSLDSLErrorLineNumbers.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2021 Google LLC.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/*****
+ * This class tests that errors are reported at the correct line numbers, so note that shifting the
+ * code up or down will break tests.
+ *****/
+#include "src/gpu/GrDirectContextPriv.h"
+#include "src/gpu/GrGpu.h"
+#include "src/sksl/SkSLIRGenerator.h"
+#include "src/sksl/dsl/DSL.h"
+#include "src/sksl/dsl/priv/DSLWriter.h"
+#include "src/sksl/ir/SkSLIRNode.h"
+
+#include "tests/Test.h"
+
+#include <limits>
+
+using namespace SkSL::dsl;
+
+#if defined(__GNUC__) || defined(__clang__)
+
+class ExpectErrorLineNumber : public ErrorHandler {
+public:
+    ExpectErrorLineNumber(skiatest::Reporter* reporter, const char* msg, int line)
+        : fMsg(msg)
+        , fLine(line)
+        , fReporter(reporter) {
+        SetErrorHandler(this);
+    }
+
+    ~ExpectErrorLineNumber() override {
+        REPORTER_ASSERT(fReporter, !fMsg);
+        SetErrorHandler(nullptr);
+    }
+
+    void handleError(const char* msg, PositionInfo* pos) override {
+        REPORTER_ASSERT(fReporter, !strcmp(msg, fMsg),
+                        "Error mismatch: expected:\n%sbut received:\n%s", fMsg, msg);
+        REPORTER_ASSERT(fReporter, pos);
+        REPORTER_ASSERT(fReporter, pos->line() == fLine,
+                        "Line number mismatch: expected %d, but received %d\n", fLine, pos->line());
+        fMsg = nullptr;
+    }
+
+private:
+    const char* fMsg;
+    int fLine;
+    skiatest::Reporter* fReporter;
+};
+
+DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLErrorLineNumbers, r, ctxInfo) {
+    Start(ctxInfo.directContext()->priv().getGpu()->shaderCompiler());
+    {
+        ExpectErrorLineNumber error(r,
+                                    "error: type mismatch: '+' cannot operate on 'float', 'bool'\n",
+                                    62);
+        DSLExpression x = (Float(1) + true);
+    }
+
+    {
+        Var a(kBool);
+        ExpectErrorLineNumber error(r,
+                                    "error: type mismatch: '=' cannot operate on 'bool', 'float'\n",
+                                    70);
+        DSLExpression x = (a = 5.0f);
+    }
+
+    {
+        Var a(Array(kInt, 5));
+        ExpectErrorLineNumber error(r,
+                                    "error: expected 'int', but found 'bool'\n",
+                                    78);
+        DSLExpression x = (a[true]);
+    }
+
+    {
+        Var a(Array(kInt, 5));
+        ExpectErrorLineNumber error(r,
+                                    "error: '++' cannot operate on 'int[5]'\n",
+                                    86);
+        DSLExpression x = ++a;
+    }
+
+    {
+        ExpectErrorLineNumber error(r,
+                                    "error: expected 'bool', but found 'int'\n",
+                                    93);
+        DSLStatement x = Do(Discard(), 5);
+    }
+
+    {
+        ExpectErrorLineNumber error(r,
+                                    "error: expected 'bool', but found 'int'\n",
+                                    100);
+        DSLStatement x = For(DSLStatement(), 5, DSLExpression(), DSLStatement());
+    }
+
+    {
+        ExpectErrorLineNumber error(r,
+                                    "error: expected 'bool', but found 'int'\n",
+                                    107);
+        DSLStatement x = If(5, Discard());
+    }
+
+    {
+        ExpectErrorLineNumber error(r,
+                                    "error: expected 'bool', but found 'int'\n",
+                                    114);
+        DSLStatement x = While(5, Discard());
+    }
+
+    {
+        ExpectErrorLineNumber error(r,
+                                    "error: no match for abs(bool)\n",
+                                    121);
+        DSLStatement x = Abs(true);
+    }
+    End();
+}
+
+#endif // defined(__GNUC__) || defined(__clang__)
diff --git a/tests/SkSLDSLTest.cpp b/tests/SkSLDSLTest.cpp
index 0055f78..ac73b93 100644
--- a/tests/SkSLDSLTest.cpp
+++ b/tests/SkSLDSLTest.cpp
@@ -96,8 +96,10 @@
     REPORTER_ASSERT(r, !whitespace_insensitive_compare("a b c  d", "\n\n\nabc"));
 }
 
-static SkSL::String stringize(DSLStatement& stmt)  { return stmt.release()->description(); }
-static SkSL::String stringize(DSLExpression& expr) { return expr.release()->description(); }
+static SkSL::String stringize(DSLStatement& stmt)          { return stmt.release()->description(); }
+static SkSL::String stringize(DSLPossibleStatement& stmt)  { return stmt.release()->description(); }
+static SkSL::String stringize(DSLExpression& expr)         { return expr.release()->description(); }
+static SkSL::String stringize(DSLPossibleExpression& expr) { return expr.release()->description(); }
 static SkSL::String stringize(SkSL::IRNode& node)  { return node.description(); }
 
 template <typename T>
@@ -379,17 +381,17 @@
 
     {
         ExpectError error(r, "error: type mismatch: '+' cannot operate on 'bool2', 'float'\n");
-        (Bool2(true) + a).release();
+        DSLExpression((Bool2(true) + a)).release();
     }
 
     {
         ExpectError error(r, "error: type mismatch: '+=' cannot operate on 'float', 'bool2'\n");
-        (a += Bool2(true)).release();
+        DSLExpression((a += Bool2(true))).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        (1.0 += a).release();
+        DSLExpression((1.0 += a)).release();
     }
 }
 
@@ -410,17 +412,17 @@
 
     {
         ExpectError error(r, "error: type mismatch: '-' cannot operate on 'bool2', 'int'\n");
-        (Bool2(true) - a).release();
+        DSLExpression(Bool2(true) - a).release();
     }
 
     {
         ExpectError error(r, "error: type mismatch: '-=' cannot operate on 'int', 'bool2'\n");
-        (a -= Bool2(true)).release();
+        DSLExpression(a -= Bool2(true)).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        (1.0 -= a).release();
+        DSLExpression(1.0 -= a).release();
     }
 }
 
@@ -441,17 +443,17 @@
 
     {
         ExpectError error(r, "error: type mismatch: '*' cannot operate on 'bool2', 'float'\n");
-        (Bool2(true) * a).release();
+        DSLExpression(Bool2(true) * a).release();
     }
 
     {
         ExpectError error(r, "error: type mismatch: '*=' cannot operate on 'float', 'bool2'\n");
-        (a *= Bool2(true)).release();
+        DSLExpression(a *= Bool2(true)).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        (1.0 *= a).release();
+        DSLExpression(1.0 *= a).release();
     }
 }
 
@@ -475,28 +477,28 @@
 
     {
         ExpectError error(r, "error: type mismatch: '/' cannot operate on 'bool2', 'float'\n");
-        (Bool2(true) / a).release();
+        DSLExpression(Bool2(true) / a).release();
     }
 
     {
         ExpectError error(r, "error: type mismatch: '/=' cannot operate on 'float', 'bool2'\n");
-        (a /= Bool2(true)).release();
+        DSLExpression(a /= Bool2(true)).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        (1.0 /= a).release();
+        DSLExpression(1.0 /= a).release();
     }
 
     {
         ExpectError error(r, "error: division by zero\n");
-        (a /= 0).release();
+        DSLExpression(a /= 0).release();
     }
 
     {
         Var c(kFloat2, "c");
         ExpectError error(r, "error: division by zero\n");
-        (c /= Float2(Float(0), 1)).release();
+        DSLExpression(c /= Float2(Float(0), 1)).release();
     }
 }
 
@@ -517,28 +519,28 @@
 
     {
         ExpectError error(r, "error: type mismatch: '%' cannot operate on 'bool2', 'int'\n");
-        (Bool2(true) % a).release();
+        DSLExpression(Bool2(true) % a).release();
     }
 
     {
         ExpectError error(r, "error: type mismatch: '%=' cannot operate on 'int', 'bool2'\n");
-        (a %= Bool2(true)).release();
+        DSLExpression(a %= Bool2(true)).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        (1 %= a).release();
+        DSLExpression(1 %= a).release();
     }
 
     {
         ExpectError error(r, "error: division by zero\n");
-        (a %= 0).release();
+        DSLExpression(a %= 0).release();
     }
 
     {
         Var c(kInt2, "c");
         ExpectError error(r, "error: division by zero\n");
-        (c %= Int2(Int(0), 1)).release();
+        DSLExpression(c %= Int2(Int(0), 1)).release();
     }
 }
 
@@ -559,17 +561,17 @@
 
     {
         ExpectError error(r, "error: type mismatch: '<<' cannot operate on 'bool2', 'int'\n");
-        (Bool2(true) << a).release();
+        DSLExpression(Bool2(true) << a).release();
     }
 
     {
         ExpectError error(r, "error: type mismatch: '<<=' cannot operate on 'int', 'bool2'\n");
-        (a <<= Bool2(true)).release();
+        DSLExpression(a <<= Bool2(true)).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        (1 <<= a).release();
+        DSLExpression(1 <<= a).release();
     }
 }
 
@@ -590,17 +592,17 @@
 
     {
         ExpectError error(r, "error: type mismatch: '>>' cannot operate on 'bool2', 'int'\n");
-        (Bool2(true) >> a).release();
+        DSLExpression(Bool2(true) >> a).release();
     }
 
     {
         ExpectError error(r, "error: type mismatch: '>>=' cannot operate on 'int', 'bool2'\n");
-        (a >>= Bool2(true)).release();
+        DSLExpression(a >>= Bool2(true)).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        (1 >>= a).release();
+        DSLExpression(1 >>= a).release();
     }
 }
 
@@ -621,17 +623,17 @@
 
     {
         ExpectError error(r, "error: type mismatch: '&' cannot operate on 'bool2', 'int'\n");
-        (Bool2(true) & a).release();
+        DSLExpression(Bool2(true) & a).release();
     }
 
     {
         ExpectError error(r, "error: type mismatch: '&=' cannot operate on 'int', 'bool2'\n");
-        (a &= Bool2(true)).release();
+        DSLExpression(a &= Bool2(true)).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        (1 &= a).release();
+        DSLExpression(1 &= a).release();
     }
 }
 
@@ -652,17 +654,17 @@
 
     {
         ExpectError error(r, "error: type mismatch: '|' cannot operate on 'bool2', 'int'\n");
-        (Bool2(true) | a).release();
+        DSLExpression(Bool2(true) | a).release();
     }
 
     {
         ExpectError error(r, "error: type mismatch: '|=' cannot operate on 'int', 'bool2'\n");
-        (a |= Bool2(true)).release();
+        DSLExpression(a |= Bool2(true)).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        (1 |= a).release();
+        DSLExpression(1 |= a).release();
     }
 }
 
@@ -683,17 +685,17 @@
 
     {
         ExpectError error(r, "error: type mismatch: '^' cannot operate on 'bool2', 'int'\n");
-        (Bool2(true) ^ a).release();
+        DSLExpression(Bool2(true) ^ a).release();
     }
 
     {
         ExpectError error(r, "error: type mismatch: '^=' cannot operate on 'int', 'bool2'\n");
-        (a ^= Bool2(true)).release();
+        DSLExpression(a ^= Bool2(true)).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        (1 ^= a).release();
+        DSLExpression(1 ^= a).release();
     }
 }
 
@@ -711,7 +713,7 @@
 
     {
         ExpectError error(r, "error: type mismatch: '&&' cannot operate on 'bool', 'int'\n");
-        (a && 5).release();
+        DSLExpression(a && 5).release();
     }
 }
 
@@ -729,7 +731,7 @@
 
     {
         ExpectError error(r, "error: type mismatch: '||' cannot operate on 'bool', 'int'\n");
-        (a || 5).release();
+        DSLExpression(a || 5).release();
     }
 }
 
@@ -754,7 +756,7 @@
 
     {
         ExpectError error(r, "error: type mismatch: '==' cannot operate on 'int', 'bool2'\n");
-        (a == Bool2(true)).release();
+        DSLExpression(a == Bool2(true)).release();
     }
 }
 
@@ -769,7 +771,7 @@
 
     {
         ExpectError error(r, "error: type mismatch: '!=' cannot operate on 'int', 'bool2'\n");
-        (a != Bool2(true)).release();
+        DSLExpression(a != Bool2(true)).release();
     }
 }
 
@@ -784,7 +786,7 @@
 
     {
         ExpectError error(r, "error: type mismatch: '>' cannot operate on 'int', 'bool2'\n");
-        (a > Bool2(true)).release();
+        DSLExpression(a > Bool2(true)).release();
     }
 }
 
@@ -799,7 +801,7 @@
 
     {
         ExpectError error(r, "error: type mismatch: '>=' cannot operate on 'int', 'bool2'\n");
-        (a >= Bool2(true)).release();
+        DSLExpression(a >= Bool2(true)).release();
     }
 }
 
@@ -814,7 +816,7 @@
 
     {
         ExpectError error(r, "error: type mismatch: '<' cannot operate on 'int', 'bool2'\n");
-        (a < Bool2(true)).release();
+        DSLExpression(a < Bool2(true)).release();
     }
 }
 
@@ -829,7 +831,7 @@
 
     {
         ExpectError error(r, "error: type mismatch: '<=' cannot operate on 'int', 'bool2'\n");
-        (a <= Bool2(true)).release();
+        DSLExpression(a <= Bool2(true)).release();
     }
 }
 
@@ -841,7 +843,7 @@
 
     {
         ExpectError error(r, "error: '!' cannot operate on 'int'\n");
-        (!a).release();
+        DSLExpression(!a).release();
     }
 }
 
@@ -853,7 +855,7 @@
 
     {
         ExpectError error(r, "error: '~' cannot operate on 'bool'\n");
-        (~b).release();
+        DSLExpression(~b).release();
     }
 }
 
@@ -868,22 +870,22 @@
 
     {
         ExpectError error(r, "error: '++' cannot operate on 'bool'\n");
-        (++b).release();
+        DSLExpression(++b).release();
     }
 
     {
         ExpectError error(r, "error: '++' cannot operate on 'bool'\n");
-        (b++).release();
+        DSLExpression(b++).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        (++(a + 1)).release();
+        DSLExpression(++(a + 1)).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        ((a + 1)++).release();
+        DSLExpression((a + 1)++).release();
     }
 }
 
@@ -898,22 +900,22 @@
 
     {
         ExpectError error(r, "error: '--' cannot operate on 'bool'\n");
-        (--b).release();
+        DSLExpression(--b).release();
     }
 
     {
         ExpectError error(r, "error: '--' cannot operate on 'bool'\n");
-        (b--).release();
+        DSLExpression(b--).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        (--(a + 1)).release();
+        DSLExpression(--(a + 1)).release();
     }
 
     {
         ExpectError error(r, "error: cannot assign to this expression\n");
-        ((a + 1)--).release();
+        DSLExpression((a + 1)--).release();
     }
 }
 
@@ -1122,12 +1124,12 @@
 
     {
         ExpectError error(r, "error: expected 'bool', but found 'int'\n");
-        Select(a, 1, -1).release();
+        DSLExpression x = Select(a, 1, -1);
     }
 
     {
         ExpectError error(r, "error: ternary operator result mismatch: 'float2', 'float3'\n");
-        Select(a > 0, Float2(1), Float3(1)).release();
+        DSLExpression x = Select(a > 0, Float2(1), Float3(1));
     }
 }
 
@@ -1159,18 +1161,18 @@
 
     {
         ExpectError error(r, "error: duplicate case value '0'\n");
-        Switch(0, Case(0), Case(0)).release();
+        DSLStatement(Switch(0, Case(0), Case(0))).release();
     }
 
     {
         ExpectError error(r, "error: duplicate default case\n");
-        Switch(0, Default(a = 0), Default(a = 1)).release();
+        DSLStatement(Switch(0, Default(a = 0), Default(a = 1))).release();
     }
 
     {
         ExpectError error(r, "error: case value must be a constant integer\n");
         Var b(kInt);
-        Switch(0, Case(b)).release();
+        DSLStatement(Switch(0, Case(b))).release();
     }
 
     {
@@ -1240,7 +1242,7 @@
 
     {
         ExpectError error(r, "error: expected 'bool', but found 'int'\n");
-        While(7, Block()).release();
+        DSLStatement x = While(7, Block());
     }
 }
 
@@ -1253,17 +1255,17 @@
 
     {
         ExpectError error(r, "error: expected 'int', but found 'bool'\n");
-        a[true].release();
+        DSLExpression x = a[true];
     }
 
     {
         ExpectError error(r, "error: expected array, but found 'int'\n");
-        b[0].release();
+        DSLExpression x = b[0];
     }
 
     {
         ExpectError error(r, "error: index -1 out of range for 'int[5]'\n");
-        a[-1].release();
+        DSLExpression x = a[-1];
     }
 }