Migrate to using semantic::Expression

Remove the mutable `result_type` from the ast::Expression.
Replace this with the use of semantic::Expression.

Bug: tint:390
Change-Id: I1f0eaf0dce8fde46fefe50bf2c5fe5b2e4d2d2df
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/39007
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/type_determiner.cc b/src/type_determiner.cc
index bf5e601..4256651 100644
--- a/src/type_determiner.cc
+++ b/src/type_determiner.cc
@@ -43,6 +43,7 @@
 #include "src/ast/unary_op_expression.h"
 #include "src/ast/variable_decl_statement.h"
 #include "src/program_builder.h"
+#include "src/semantic/expression.h"
 #include "src/type/array_type.h"
 #include "src/type/bool_type.h"
 #include "src/type/depth_texture_type.h"
@@ -308,6 +309,10 @@
     return true;
   }
 
+  if (TypeOf(expr)) {
+    return true;  // Already resolved
+  }
+
   if (auto* a = expr->As<ast::ArrayAccessorExpression>()) {
     return DetermineArrayAccessor(a);
   }
@@ -346,7 +351,7 @@
     return false;
   }
 
-  auto* res = expr->array()->result_type();
+  auto* res = TypeOf(expr->array());
   auto* parent_type = res->UnwrapAll();
   type::Type* ret = nullptr;
   if (auto* arr = parent_type->As<type::Array>()) {
@@ -373,7 +378,7 @@
       ret = builder_->create<type::Pointer>(ret, ast::StorageClass::kFunction);
     }
   }
-  expr->set_result_type(ret);
+  SetType(expr, ret);
 
   return true;
 }
@@ -382,7 +387,7 @@
   if (!DetermineResultType(expr->expr())) {
     return false;
   }
-  expr->set_result_type(expr->type());
+  SetType(expr, expr->type());
   return true;
 }
 
@@ -420,12 +425,6 @@
           set_referenced_from_function_if_needed(var, false);
         }
       }
-
-      // An identifier with a single name is a function call, not an import
-      // lookup which we can handle with the regular identifier lookup.
-      if (!DetermineResultType(ident)) {
-        return false;
-      }
     }
   } else {
     if (!DetermineResultType(expr->func())) {
@@ -433,7 +432,9 @@
     }
   }
 
-  if (!expr->func()->result_type()) {
+  if (auto* type = TypeOf(expr->func())) {
+    SetType(expr, type);
+  } else {
     auto func_sym = expr->func()->As<ast::IdentifierExpression>()->symbol();
     set_error(expr->source(),
               "v-0005: function must be declared before use: '" +
@@ -441,7 +442,6 @@
     return false;
   }
 
-  expr->set_result_type(expr->func()->result_type());
   return true;
 }
 
@@ -530,17 +530,17 @@
     }
 
     // The result type must be the same as the type of the parameter.
-    auto* param_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
-    expr->func()->set_result_type(param_type);
+    auto* param_type = TypeOf(expr->params()[0])->UnwrapPtrIfNeeded();
+    SetType(expr->func(), param_type);
     return true;
   }
   if (ident->intrinsic() == ast::Intrinsic::kAny ||
       ident->intrinsic() == ast::Intrinsic::kAll) {
-    expr->func()->set_result_type(builder_->create<type::Bool>());
+    SetType(expr->func(), builder_->create<type::Bool>());
     return true;
   }
   if (ident->intrinsic() == ast::Intrinsic::kArrayLength) {
-    expr->func()->set_result_type(builder_->create<type::U32>());
+    SetType(expr->func(), builder_->create<type::U32>());
     return true;
   }
   if (ast::intrinsic::IsFloatClassificationIntrinsic(ident->intrinsic())) {
@@ -553,12 +553,12 @@
 
     auto* bool_type = builder_->create<type::Bool>();
 
-    auto* param_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
+    auto* param_type = TypeOf(expr->params()[0])->UnwrapPtrIfNeeded();
     if (auto* vec = param_type->As<type::Vector>()) {
-      expr->func()->set_result_type(
-          builder_->create<type::Vector>(bool_type, vec->size()));
+      SetType(expr->func(),
+              builder_->create<type::Vector>(bool_type, vec->size()));
     } else {
-      expr->func()->set_result_type(bool_type);
+      SetType(expr->func(), bool_type);
     }
     return true;
   }
@@ -566,14 +566,14 @@
     ast::intrinsic::TextureSignature::Parameters param;
 
     auto* texture_param = expr->params()[0];
-    if (!texture_param->result_type()->UnwrapAll()->Is<type::Texture>()) {
+    if (!TypeOf(texture_param)->UnwrapAll()->Is<type::Texture>()) {
       set_error(expr->source(),
                 "invalid first argument for " +
                     builder_->Symbols().NameFor(ident->symbol()));
       return false;
     }
     type::Texture* texture =
-        texture_param->result_type()->UnwrapAll()->As<type::Texture>();
+        TypeOf(texture_param)->UnwrapAll()->As<type::Texture>();
 
     bool is_array = type::IsTextureArray(texture->dim());
     bool is_multisampled = texture->Is<type::MultisampledTexture>();
@@ -744,12 +744,12 @@
         }
       }
     }
-    expr->func()->set_result_type(return_type);
+    SetType(expr->func(), return_type);
 
     return true;
   }
   if (ident->intrinsic() == ast::Intrinsic::kDot) {
-    expr->func()->set_result_type(builder_->create<type::F32>());
+    SetType(expr->func(), builder_->create<type::F32>());
     return true;
   }
   if (ident->intrinsic() == ast::Intrinsic::kSelect) {
@@ -762,8 +762,8 @@
     }
 
     // The result type must be the same as the type of the parameter.
-    auto* param_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
-    expr->func()->set_result_type(param_type);
+    auto* param_type = TypeOf(expr->params()[0])->UnwrapPtrIfNeeded();
+    SetType(expr->func(), param_type);
     return true;
   }
 
@@ -791,8 +791,7 @@
 
   std::vector<type::Type*> result_types;
   for (uint32_t i = 0; i < data->param_count; ++i) {
-    result_types.push_back(
-        expr->params()[i]->result_type()->UnwrapPtrIfNeeded());
+    result_types.push_back(TypeOf(expr->params()[i])->UnwrapPtrIfNeeded());
 
     switch (data->data_type) {
       case IntrinsicDataType::kFloatOrIntScalarOrVector:
@@ -869,18 +868,17 @@
   // provided.
   if (ident->intrinsic() == ast::Intrinsic::kLength ||
       ident->intrinsic() == ast::Intrinsic::kDistance) {
-    expr->func()->set_result_type(
-        result_types[0]->is_float_scalar()
-            ? result_types[0]
-            : result_types[0]->As<type::Vector>()->type());
+    SetType(expr->func(), result_types[0]->is_float_scalar()
+                              ? result_types[0]
+                              : result_types[0]->As<type::Vector>()->type());
     return true;
   }
   // The determinant returns the component type of the columns
   if (ident->intrinsic() == ast::Intrinsic::kDeterminant) {
-    expr->func()->set_result_type(result_types[0]->As<type::Matrix>()->type());
+    SetType(expr->func(), result_types[0]->As<type::Matrix>()->type());
     return true;
   }
-  expr->func()->set_result_type(result_types[0]);
+  SetType(expr->func(), result_types[0]);
   return true;
 }
 
@@ -891,10 +889,10 @@
         return false;
       }
     }
-    expr->set_result_type(ty->type());
+    SetType(expr, ty->type());
   } else {
-    expr->set_result_type(
-        expr->As<ast::ScalarConstructorExpression>()->literal()->type());
+    SetType(expr,
+            expr->As<ast::ScalarConstructorExpression>()->literal()->type());
   }
   return true;
 }
@@ -906,12 +904,12 @@
     // A constant is the type, but a variable is always a pointer so synthesize
     // the pointer around the variable type.
     if (var->is_const()) {
-      expr->set_result_type(var->type());
+      SetType(expr, var->type());
     } else if (var->type()->Is<type::Pointer>()) {
-      expr->set_result_type(var->type());
+      SetType(expr, var->type());
     } else {
-      expr->set_result_type(
-          builder_->create<type::Pointer>(var->type(), var->storage_class()));
+      SetType(expr, builder_->create<type::Pointer>(var->type(),
+                                                    var->storage_class()));
     }
 
     set_referenced_from_function_if_needed(var, true);
@@ -920,7 +918,7 @@
 
   auto iter = symbol_to_function_.find(symbol);
   if (iter != symbol_to_function_.end()) {
-    expr->set_result_type(iter->second->return_type());
+    SetType(expr, iter->second->return_type());
     return true;
   }
 
@@ -1091,7 +1089,7 @@
     return false;
   }
 
-  auto* res = expr->structure()->result_type();
+  auto* res = TypeOf(expr->structure());
   auto* data_type = res->UnwrapPtrIfNeeded()->UnwrapIfNeeded();
 
   type::Type* ret = nullptr;
@@ -1143,7 +1141,7 @@
     return false;
   }
 
-  expr->set_result_type(ret);
+  SetType(expr, ret);
 
   return true;
 }
@@ -1157,7 +1155,7 @@
   if (expr->IsAnd() || expr->IsOr() || expr->IsXor() || expr->IsShiftLeft() ||
       expr->IsShiftRight() || expr->IsAdd() || expr->IsSubtract() ||
       expr->IsDivide() || expr->IsModulo()) {
-    expr->set_result_type(expr->lhs()->result_type()->UnwrapPtrIfNeeded());
+    SetType(expr, TypeOf(expr->lhs())->UnwrapPtrIfNeeded());
     return true;
   }
   // Result type is a scalar or vector of boolean type
@@ -1165,18 +1163,17 @@
       expr->IsNotEqual() || expr->IsLessThan() || expr->IsGreaterThan() ||
       expr->IsLessThanEqual() || expr->IsGreaterThanEqual()) {
     auto* bool_type = builder_->create<type::Bool>();
-    auto* param_type = expr->lhs()->result_type()->UnwrapPtrIfNeeded();
+    auto* param_type = TypeOf(expr->lhs())->UnwrapPtrIfNeeded();
+    type::Type* result_type = bool_type;
     if (auto* vec = param_type->As<type::Vector>()) {
-      expr->set_result_type(
-          builder_->create<type::Vector>(bool_type, vec->size()));
-    } else {
-      expr->set_result_type(bool_type);
+      result_type = builder_->create<type::Vector>(bool_type, vec->size());
     }
+    SetType(expr, result_type);
     return true;
   }
   if (expr->IsMultiply()) {
-    auto* lhs_type = expr->lhs()->result_type()->UnwrapPtrIfNeeded();
-    auto* rhs_type = expr->rhs()->result_type()->UnwrapPtrIfNeeded();
+    auto* lhs_type = TypeOf(expr->lhs())->UnwrapPtrIfNeeded();
+    auto* rhs_type = TypeOf(expr->rhs())->UnwrapPtrIfNeeded();
 
     // Note, the ordering here matters. The later checks depend on the prior
     // checks having been done.
@@ -1184,34 +1181,36 @@
     auto* rhs_mat = rhs_type->As<type::Matrix>();
     auto* lhs_vec = lhs_type->As<type::Vector>();
     auto* rhs_vec = rhs_type->As<type::Vector>();
+    type::Type* result_type;
     if (lhs_mat && rhs_mat) {
-      expr->set_result_type(builder_->create<type::Matrix>(
-          lhs_mat->type(), lhs_mat->rows(), rhs_mat->columns()));
+      result_type = builder_->create<type::Matrix>(
+          lhs_mat->type(), lhs_mat->rows(), rhs_mat->columns());
     } else if (lhs_mat && rhs_vec) {
-      expr->set_result_type(
-          builder_->create<type::Vector>(lhs_mat->type(), lhs_mat->rows()));
+      result_type =
+          builder_->create<type::Vector>(lhs_mat->type(), lhs_mat->rows());
     } else if (lhs_vec && rhs_mat) {
-      expr->set_result_type(
-          builder_->create<type::Vector>(rhs_mat->type(), rhs_mat->columns()));
+      result_type =
+          builder_->create<type::Vector>(rhs_mat->type(), rhs_mat->columns());
     } else if (lhs_mat) {
       // matrix * scalar
-      expr->set_result_type(lhs_type);
+      result_type = lhs_type;
     } else if (rhs_mat) {
       // scalar * matrix
-      expr->set_result_type(rhs_type);
+      result_type = rhs_type;
     } else if (lhs_vec && rhs_vec) {
-      expr->set_result_type(lhs_type);
+      result_type = lhs_type;
     } else if (lhs_vec) {
       // Vector * scalar
-      expr->set_result_type(lhs_type);
+      result_type = lhs_type;
     } else if (rhs_vec) {
       // Scalar * vector
-      expr->set_result_type(rhs_type);
+      result_type = rhs_type;
     } else {
       // Scalar * Scalar
-      expr->set_result_type(lhs_type);
+      result_type = lhs_type;
     }
 
+    SetType(expr, result_type);
     return true;
   }
 
@@ -1224,7 +1223,9 @@
   if (!DetermineResultType(expr->expr())) {
     return false;
   }
-  expr->set_result_type(expr->expr()->result_type()->UnwrapPtrIfNeeded());
+
+  auto* result_type = TypeOf(expr->expr())->UnwrapPtrIfNeeded();
+  SetType(expr, result_type);
   return true;
 }
 
@@ -1288,4 +1289,9 @@
   return false;
 }
 
+void TypeDeterminer::SetType(ast::Expression* expr, type::Type* type) const {
+  return builder_->Sem().Add(expr,
+                             builder_->create<semantic::Expression>(type));
+}
+
 }  // namespace tint