// Copyright 2021 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef SRC_TINT_LANG_WGSL_RESOLVER_RESOLVER_HELPER_TEST_H_
#define SRC_TINT_LANG_WGSL_RESOLVER_RESOLVER_HELPER_TEST_H_

#include <functional>
#include <memory>
#include <ostream>
#include <string>
#include <tuple>
#include <utility>
#include <variant>

#include "gtest/gtest.h"
#include "src/tint/lang/core/type/abstract_float.h"
#include "src/tint/lang/core/type/abstract_int.h"
#include "src/tint/lang/wgsl/program/program_builder.h"
#include "src/tint/lang/wgsl/resolver/resolver.h"
#include "src/tint/lang/wgsl/sem/array.h"
#include "src/tint/lang/wgsl/sem/statement.h"
#include "src/tint/lang/wgsl/sem/value_expression.h"
#include "src/tint/lang/wgsl/sem/variable.h"
#include "src/tint/utils/containers/vector.h"
#include "src/tint/utils/traits/traits.h"

namespace tint::resolver {

/// Helper class for testing
class TestHelper : public ProgramBuilder {
  public:
    /// Constructor
    TestHelper();

    /// Destructor
    ~TestHelper();

    /// @return a pointer to the Resolver
    Resolver* r() const { return resolver_.get(); }

    /// @return a pointer to the validator
    const Validator* v() const { return resolver_->GetValidatorForTesting(); }

    /// Returns the statement that holds the given expression.
    /// @param expr the ast::Expression
    /// @return the ast::Statement of the ast::Expression, or nullptr if the
    /// expression is not owned by a statement.
    const ast::Statement* StmtOf(const ast::Expression* expr) {
        auto* sem_stmt = Sem().Get(expr)->Stmt();
        return sem_stmt ? sem_stmt->Declaration() : nullptr;
    }

    /// Returns the BlockStatement that holds the given statement.
    /// @param stmt the ast::Statement
    /// @return the ast::BlockStatement that holds the ast::Statement, or nullptr
    /// if the statement is not owned by a BlockStatement.
    const ast::BlockStatement* BlockOf(const ast::Statement* stmt) {
        auto* sem_stmt = Sem().Get(stmt);
        return sem_stmt ? sem_stmt->Block()->Declaration() : nullptr;
    }

    /// Returns the BlockStatement that holds the given expression.
    /// @param expr the ast::Expression
    /// @return the ast::Statement of the ast::Expression, or nullptr if the
    /// expression is not indirectly owned by a BlockStatement.
    const ast::BlockStatement* BlockOf(const ast::Expression* expr) {
        auto* sem_stmt = Sem().Get(expr)->Stmt();
        return sem_stmt ? sem_stmt->Block()->Declaration() : nullptr;
    }

    /// Returns the semantic variable for the given identifier expression.
    /// @param expr the identifier expression
    /// @return the resolved sem::Variable of the identifier, or nullptr if
    /// the expression did not resolve to a variable.
    const sem::Variable* VarOf(const ast::Expression* expr) {
        if (auto* sem = Sem().GetVal(expr)) {
            if (auto* var_user = As<sem::VariableUser>(sem->UnwrapLoad())) {
                return var_user->Variable();
            }
        }
        return nullptr;
    }

    /// Checks that all the users of the given variable are as expected
    /// @param var the variable to check
    /// @param expected_users the expected users of the variable
    /// @return true if all users are as expected
    bool CheckVarUsers(const ast::Variable* var, VectorRef<const ast::Expression*> expected_users) {
        auto var_users = Sem().Get(var)->Users();
        if (var_users.Length() != expected_users.Length()) {
            return false;
        }
        for (size_t i = 0; i < var_users.Length(); i++) {
            if (var_users[i]->Declaration() != expected_users[i]) {
                return false;
            }
        }
        return true;
    }

    /// @param type a type
    /// @returns the name for `type` that closely resembles how it would be
    /// declared in WGSL.
    std::string FriendlyName(ast::Type type) { return type->identifier->symbol.Name(); }

    /// @param type a type
    /// @returns the name for `type` that closely resembles how it would be
    /// declared in WGSL.
    std::string FriendlyName(const core::type::Type* type) { return type->FriendlyName(); }

  private:
    std::unique_ptr<Resolver> resolver_;
};

class ResolverTest : public TestHelper, public testing::Test {};

template <typename T>
class ResolverTestWithParam : public TestHelper, public testing::TestWithParam<T> {};

namespace builder {

template <typename TO, int ID = 0>
struct alias {};

template <typename TO>
using alias1 = alias<TO, 1>;

template <typename TO>
using alias2 = alias<TO, 2>;

template <typename TO>
using alias3 = alias<TO, 3>;

/// Scalar represents a scalar value
struct Scalar {
    /// The possible types of a scalar value.
    using Value =
        std::variant<core::i32, core::u32, core::f32, core::f16, core::AInt, core::AFloat, bool>;

    /// Constructor
    /// @param val the value used to construct this Scalar
    template <typename T>
    Scalar(T&& val) : value(std::forward<T>(val)) {}  // NOLINT

    /// @returns the Value
    operator Value&() { return value; }

    /// Equality operator
    /// @param other the other Scalar
    /// @return true if this Scalar is equal to @p other
    bool operator==(const Scalar& other) const { return value == other.value; }

    /// Inequality operator
    /// @param other the other Scalar
    /// @return true if this Scalar is not equal to @p other
    bool operator!=(const Scalar& other) const { return value != other.value; }

    /// The scalar value
    Value value;
};

/// @param out the stream to write to
/// @param s the Scalar
/// @returns @p out so calls can be chained
template <typename STREAM, typename = traits::EnableIfIsOStream<STREAM>>
STREAM& operator<<(STREAM& out, const Scalar& s) {
    std::visit([&](auto&& v) { out << v; }, s.value);
    return out;
}

/// @return  current variant value in @p s cast to type `T`
template <typename T>
T As(const Scalar& s) {
    return std::visit([](auto&& v) { return static_cast<T>(v); }, s.value);
}

using ast_type_func_ptr = ast::Type (*)(ProgramBuilder& b);
using ast_expr_func_ptr = const ast::Expression* (*)(ProgramBuilder& b, VectorRef<Scalar> args);
using ast_expr_from_double_func_ptr = const ast::Expression* (*)(ProgramBuilder& b, double v);
using sem_type_func_ptr = const core::type::Type* (*)(ProgramBuilder& b);
using type_name_func_ptr = std::string (*)();

struct UnspecializedElementType {};

/// Base template for DataType, specialized below.
template <typename T>
struct DataType {
    /// The element type
    using ElementType = UnspecializedElementType;
};

/// Helper that represents no-type. Returns nullptr for all static methods.
template <>
struct DataType<void> {
    /// The element type
    using ElementType = void;

    /// @return nullptr
    static inline ast::Type AST(ProgramBuilder&) { return {}; }
    /// @return nullptr
    static inline const core::type::Type* Sem(ProgramBuilder&) { return nullptr; }
};

/// Helper for building bool types and expressions
template <>
struct DataType<bool> {
    /// The element type
    using ElementType = bool;

    /// false as bool is not a composite type
    static constexpr bool is_composite = false;

    /// @param b the ProgramBuilder
    /// @return a new AST bool type
    static inline ast::Type AST(ProgramBuilder& b) { return b.ty.bool_(); }
    /// @param b the ProgramBuilder
    /// @return the semantic bool type
    static inline const core::type::Type* Sem(ProgramBuilder& b) {
        return b.create<core::type::Bool>();
    }
    /// @param b the ProgramBuilder
    /// @param args args of size 1 with the boolean value to init with
    /// @return a new AST expression of the bool type
    static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
        return b.Expr(std::get<bool>(args[0].value));
    }
    /// @param b the ProgramBuilder
    /// @param v arg of type double that will be cast to bool.
    /// @return a new AST expression of the bool type
    static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
        return Expr(b, Vector<Scalar, 1>{static_cast<ElementType>(v)});
    }
    /// @returns the WGSL name for the type
    static inline std::string Name() { return "bool"; }
};

/// Helper for building i32 types and expressions
template <>
struct DataType<core::i32> {
    /// The element type
    using ElementType = core::i32;

    /// false as i32 is not a composite type
    static constexpr bool is_composite = false;

    /// @param b the ProgramBuilder
    /// @return a new AST i32 type
    static inline ast::Type AST(ProgramBuilder& b) { return b.ty.i32(); }
    /// @param b the ProgramBuilder
    /// @return the semantic i32 type
    static inline const core::type::Type* Sem(ProgramBuilder& b) {
        return b.create<core::type::I32>();
    }
    /// @param b the ProgramBuilder
    /// @param args args of size 1 with the i32 value to init with
    /// @return a new AST i32 literal value expression
    static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
        return b.Expr(std::get<core::i32>(args[0].value));
    }
    /// @param b the ProgramBuilder
    /// @param v arg of type double that will be cast to i32.
    /// @return a new AST i32 literal value expression
    static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
        return Expr(b, Vector<Scalar, 1>{static_cast<ElementType>(v)});
    }
    /// @returns the WGSL name for the type
    static inline std::string Name() { return "i32"; }
};

/// Helper for building u32 types and expressions
template <>
struct DataType<core::u32> {
    /// The element type
    using ElementType = core::u32;

    /// false as u32 is not a composite type
    static constexpr bool is_composite = false;

    /// @param b the ProgramBuilder
    /// @return a new AST u32 type
    static inline ast::Type AST(ProgramBuilder& b) { return b.ty.u32(); }
    /// @param b the ProgramBuilder
    /// @return the semantic u32 type
    static inline const core::type::Type* Sem(ProgramBuilder& b) {
        return b.create<core::type::U32>();
    }
    /// @param b the ProgramBuilder
    /// @param args args of size 1 with the u32 value to init with
    /// @return a new AST u32 literal value expression
    static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
        return b.Expr(std::get<core::u32>(args[0].value));
    }
    /// @param b the ProgramBuilder
    /// @param v arg of type double that will be cast to u32.
    /// @return a new AST u32 literal value expression
    static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
        return Expr(b, Vector<Scalar, 1>{static_cast<ElementType>(v)});
    }
    /// @returns the WGSL name for the type
    static inline std::string Name() { return "u32"; }
};

/// Helper for building f32 types and expressions
template <>
struct DataType<core::f32> {
    /// The element type
    using ElementType = core::f32;

    /// false as f32 is not a composite type
    static constexpr bool is_composite = false;

    /// @param b the ProgramBuilder
    /// @return a new AST f32 type
    static inline ast::Type AST(ProgramBuilder& b) { return b.ty.f32(); }
    /// @param b the ProgramBuilder
    /// @return the semantic f32 type
    static inline const core::type::Type* Sem(ProgramBuilder& b) {
        return b.create<core::type::F32>();
    }
    /// @param b the ProgramBuilder
    /// @param args args of size 1 with the f32 value to init with
    /// @return a new AST f32 literal value expression
    static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
        return b.Expr(std::get<core::f32>(args[0].value));
    }
    /// @param b the ProgramBuilder
    /// @param v arg of type double that will be cast to f32.
    /// @return a new AST f32 literal value expression
    static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
        return Expr(b, Vector<Scalar, 1>{static_cast<core::f32>(v)});
    }
    /// @returns the WGSL name for the type
    static inline std::string Name() { return "f32"; }
};

/// Helper for building f16 types and expressions
template <>
struct DataType<core::f16> {
    /// The element type
    using ElementType = core::f16;

    /// false as f16 is not a composite type
    static constexpr bool is_composite = false;

    /// @param b the ProgramBuilder
    /// @return a new AST f16 type
    static inline ast::Type AST(ProgramBuilder& b) { return b.ty.f16(); }
    /// @param b the ProgramBuilder
    /// @return the semantic f16 type
    static inline const core::type::Type* Sem(ProgramBuilder& b) {
        return b.create<core::type::F16>();
    }
    /// @param b the ProgramBuilder
    /// @param args args of size 1 with the f16 value to init with
    /// @return a new AST f16 literal value expression
    static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
        return b.Expr(std::get<core::f16>(args[0].value));
    }
    /// @param b the ProgramBuilder
    /// @param v arg of type double that will be cast to f16.
    /// @return a new AST f16 literal value expression
    static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
        return Expr(b, Vector<Scalar, 1>{static_cast<ElementType>(v)});
    }
    /// @returns the WGSL name for the type
    static inline std::string Name() { return "f16"; }
};

/// Helper for building abstract float types and expressions
template <>
struct DataType<core::AFloat> {
    /// The element type
    using ElementType = core::AFloat;

    /// false as AFloat is not a composite type
    static constexpr bool is_composite = false;

    /// @returns nullptr, as abstract floats are un-typeable
    static inline ast::Type AST(ProgramBuilder&) { return {}; }
    /// @param b the ProgramBuilder
    /// @return the semantic abstract-float type
    static inline const core::type::Type* Sem(ProgramBuilder& b) {
        return b.create<core::type::AbstractFloat>();
    }
    /// @param b the ProgramBuilder
    /// @param args args of size 1 with the abstract-float value to init with
    /// @return a new AST abstract-float literal value expression
    static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
        return b.Expr(std::get<core::AFloat>(args[0].value));
    }
    /// @param b the ProgramBuilder
    /// @param v arg of type double that will be cast to AFloat.
    /// @return a new AST abstract-float literal value expression
    static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
        return Expr(b, Vector<Scalar, 1>{static_cast<ElementType>(v)});
    }
    /// @returns the WGSL name for the type
    static inline std::string Name() { return "abstract-float"; }
};

/// Helper for building abstract integer types and expressions
template <>
struct DataType<core::AInt> {
    /// The element type
    using ElementType = core::AInt;

    /// false as AFloat is not a composite type
    static constexpr bool is_composite = false;

    /// @returns nullptr, as abstract integers are un-typeable
    static inline ast::Type AST(ProgramBuilder&) { return {}; }
    /// @param b the ProgramBuilder
    /// @return the semantic abstract-int type
    static inline const core::type::Type* Sem(ProgramBuilder& b) {
        return b.create<core::type::AbstractInt>();
    }
    /// @param b the ProgramBuilder
    /// @param args args of size 1 with the abstract-int value to init with
    /// @return a new AST abstract-int literal value expression
    static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
        return b.Expr(std::get<core::AInt>(args[0].value));
    }
    /// @param b the ProgramBuilder
    /// @param v arg of type double that will be cast to AInt.
    /// @return a new AST abstract-int literal value expression
    static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
        return Expr(b, Vector<Scalar, 1>{static_cast<ElementType>(v)});
    }
    /// @returns the WGSL name for the type
    static inline std::string Name() { return "abstract-int"; }
};

/// Helper for building vector types and expressions
template <uint32_t N, typename T>
struct DataType<core::fluent_types::vec<N, T>> {
    /// The element type
    using ElementType = T;

    /// true as vectors are a composite type
    static constexpr bool is_composite = true;

    /// @param b the ProgramBuilder
    /// @return a new AST vector type
    static inline ast::Type AST(ProgramBuilder& b) {
        if (ast::IsInferOrAbstract<T>) {
            return b.ty.vec<core::fluent_types::Infer, N>();
        } else {
            return b.ty.vec(DataType<T>::AST(b), N);
        }
    }
    /// @param b the ProgramBuilder
    /// @return the semantic vector type
    static inline const core::type::Type* Sem(ProgramBuilder& b) {
        return b.create<core::type::Vector>(DataType<T>::Sem(b), N);
    }
    /// @param b the ProgramBuilder
    /// @param args args of size 1 or N with values of type T to initialize with
    /// @return a new AST vector value expression
    static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
        return b.Call(AST(b), ExprArgs(b, std::move(args)));
    }
    /// @param b the ProgramBuilder
    /// @param args args of size 1 or N with values of type T to initialize with
    /// @return the list of expressions that are used to construct the vector
    static inline auto ExprArgs(ProgramBuilder& b, VectorRef<Scalar> args) {
        const bool one_value = args.Length() == 1;
        Vector<const ast::Expression*, N> r;
        for (size_t i = 0; i < N; ++i) {
            r.Push(DataType<T>::Expr(b, Vector<Scalar, 1>{one_value ? args[0] : args[i]}));
        }
        return r;
    }
    /// @param b the ProgramBuilder
    /// @param v arg of type double that will be cast to ElementType
    /// @return a new AST vector value expression
    static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
        return Expr(b, Vector<Scalar, 1>{static_cast<ElementType>(v)});
    }
    /// @returns the WGSL name for the type
    static inline std::string Name() {
        return "vec" + std::to_string(N) + "<" + DataType<T>::Name() + ">";
    }
};

/// Helper for building matrix types and expressions
template <uint32_t N, uint32_t M, typename T>
struct DataType<core::fluent_types::mat<N, M, T>> {
    /// The element type
    using ElementType = T;

    /// true as matrices are a composite type
    static constexpr bool is_composite = true;

    /// @param b the ProgramBuilder
    /// @return a new AST matrix type
    static inline ast::Type AST(ProgramBuilder& b) {
        if (ast::IsInferOrAbstract<T>) {
            return b.ty.mat<core::fluent_types::Infer, N, M>();
        } else {
            return b.ty.mat(DataType<T>::AST(b), N, M);
        }
    }
    /// @param b the ProgramBuilder
    /// @return the semantic matrix type
    static inline const core::type::Type* Sem(ProgramBuilder& b) {
        auto* column_type = b.create<core::type::Vector>(DataType<T>::Sem(b), M);
        return b.create<core::type::Matrix>(column_type, N);
    }
    /// @param b the ProgramBuilder
    /// @param args args of size 1 or N*M with values of type T to initialize with
    /// @return a new AST matrix value expression
    static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
        return b.Call(AST(b), ExprArgs(b, std::move(args)));
    }
    /// @param b the ProgramBuilder
    /// @param args args of size 1 or N*M with values of type T to initialize with
    /// @return a new AST matrix value expression
    static inline auto ExprArgs(ProgramBuilder& b, VectorRef<Scalar> args) {
        const bool one_value = args.Length() == 1;
        size_t next = 0;
        Vector<const ast::Expression*, N> r;
        for (uint32_t i = 0; i < N; ++i) {
            if (one_value) {
                r.Push(
                    DataType<core::fluent_types::vec<M, T>>::Expr(b, Vector<Scalar, 1>{args[0]}));
            } else {
                Vector<Scalar, M> v;
                for (size_t j = 0; j < M; ++j) {
                    v.Push(args[next++]);
                }
                r.Push(DataType<core::fluent_types::vec<M, T>>::Expr(b, std::move(v)));
            }
        }
        return r;
    }
    /// @param b the ProgramBuilder
    /// @param v arg of type double that will be cast to ElementType
    /// @return a new AST matrix value expression
    static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
        return Expr(b, Vector<Scalar, 1>{static_cast<ElementType>(v)});
    }
    /// @returns the WGSL name for the type
    static inline std::string Name() {
        return "mat" + std::to_string(N) + "x" + std::to_string(M) + "<" + DataType<T>::Name() +
               ">";
    }
};

/// Helper for building alias types and expressions
template <typename T, int ID>
struct DataType<alias<T, ID>> {
    /// The element type
    using ElementType = typename DataType<T>::ElementType;

    /// true if the aliased type is a composite type
    static constexpr bool is_composite = DataType<T>::is_composite;

    /// @param b the ProgramBuilder
    /// @return a new AST alias type
    static inline ast::Type AST(ProgramBuilder& b) {
        auto name = b.Symbols().Register("alias_" + std::to_string(ID));
        if (!b.AST().LookupType(name)) {
            auto type = DataType<T>::AST(b);
            b.AST().AddTypeDecl(b.ty.alias(name, type));
        }
        return b.ty(name);
    }

    /// @param b the ProgramBuilder
    /// @return the semantic aliased type
    static inline const core::type::Type* Sem(ProgramBuilder& b) { return DataType<T>::Sem(b); }

    /// @param b the ProgramBuilder
    /// @param args the value nested elements will be initialized with
    /// @return a new AST expression of the alias type
    template <bool IS_COMPOSITE = is_composite>
    static inline tint::traits::EnableIf<!IS_COMPOSITE, const ast::Expression*> Expr(
        ProgramBuilder& b,
        VectorRef<Scalar> args) {
        // Cast
        return b.Call(AST(b), DataType<T>::Expr(b, std::move(args)));
    }

    /// @param b the ProgramBuilder
    /// @param args the value nested elements will be initialized with
    /// @return a new AST expression of the alias type
    template <bool IS_COMPOSITE = is_composite>
    static inline tint::traits::EnableIf<IS_COMPOSITE, const ast::Expression*> Expr(
        ProgramBuilder& b,
        VectorRef<Scalar> args) {
        // Construct
        return b.Call(AST(b), DataType<T>::ExprArgs(b, std::move(args)));
    }

    /// @param b the ProgramBuilder
    /// @param v arg of type double that will be cast to ElementType
    /// @return a new AST expression of the alias type
    static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
        return Expr(b, Vector<Scalar, 1>{static_cast<ElementType>(v)});
    }

    /// @returns the WGSL name for the type
    static inline std::string Name() { return "alias_" + std::to_string(ID); }
};

/// Helper for building pointer types and expressions
template <typename T>
struct DataType<
    core::fluent_types::ptr<core::AddressSpace::kPrivate, T, core::Access::kUndefined>> {
    /// The element type
    using ElementType = typename DataType<T>::ElementType;

    /// true if the pointer type is a composite type
    static constexpr bool is_composite = false;

    /// @param b the ProgramBuilder
    /// @return a new AST alias type
    static inline ast::Type AST(ProgramBuilder& b) {
        return b.ty.ptr<core::AddressSpace::kPrivate, T>();
    }

    /// @param b the ProgramBuilder
    /// @return the semantic aliased type
    static inline const core::type::Type* Sem(ProgramBuilder& b) {
        return b.create<core::type::Pointer>(core::AddressSpace::kPrivate, DataType<T>::Sem(b),
                                             core::Access::kReadWrite);
    }

    /// @param b the ProgramBuilder
    /// @return a new AST expression of the pointer type
    static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> /*unused*/) {
        auto sym = b.Symbols().New("global_for_ptr");
        b.GlobalVar(sym, DataType<T>::AST(b), core::AddressSpace::kPrivate);
        return b.AddressOf(sym);
    }

    /// @param b the ProgramBuilder
    /// @param v arg of type double that will be cast to ElementType
    /// @return a new AST expression of the pointer type
    static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
        return Expr(b, Vector<Scalar, 1>{static_cast<ElementType>(v)});
    }

    /// @returns the WGSL name for the type
    static inline std::string Name() { return "ptr<" + DataType<T>::Name() + ">"; }
};

/// Helper for building array types and expressions
template <typename T, uint32_t N>
struct DataType<core::fluent_types::array<T, N>> {
    /// The element type
    using ElementType = typename DataType<T>::ElementType;

    /// true as arrays are a composite type
    static constexpr bool is_composite = true;

    /// @param b the ProgramBuilder
    /// @return a new AST array type
    static inline ast::Type AST(ProgramBuilder& b) {
        if (auto ast = DataType<T>::AST(b)) {
            return b.ty.array(ast, core::u32(N));
        }
        return b.ty.array<core::fluent_types::Infer>();
    }
    /// @param b the ProgramBuilder
    /// @return the semantic array type
    static inline const core::type::Type* Sem(ProgramBuilder& b) {
        auto* el = DataType<T>::Sem(b);
        const core::type::ArrayCount* count = nullptr;
        if (N == 0) {
            count = b.create<core::type::RuntimeArrayCount>();
        } else {
            count = b.create<core::type::ConstantArrayCount>(N);
        }
        return b.create<sem::Array>(
            /* element */ el,
            /* count */ count,
            /* align */ el->Align(),
            /* size */ N * el->Size(),
            /* stride */ el->Align(),
            /* implicit_stride */ el->Align());
    }
    /// @param b the ProgramBuilder
    /// @param args args of size 1 or N with values of type T to initialize with
    /// with
    /// @return a new AST array value expression
    static inline const ast::Expression* Expr(ProgramBuilder& b, VectorRef<Scalar> args) {
        return b.Call(AST(b), ExprArgs(b, std::move(args)));
    }
    /// @param b the ProgramBuilder
    /// @param args args of size 1 or N with values of type T to initialize with
    /// @return the list of expressions that are used to construct the array
    static inline auto ExprArgs(ProgramBuilder& b, VectorRef<Scalar> args) {
        const bool one_value = args.Length() == 1;
        Vector<const ast::Expression*, N> r;
        for (uint32_t i = 0; i < N; i++) {
            r.Push(DataType<T>::Expr(b, Vector<Scalar, 1>{one_value ? args[0] : args[i]}));
        }
        return r;
    }
    /// @param b the ProgramBuilder
    /// @param v arg of type double that will be cast to ElementType
    /// @return a new AST array value expression
    static inline const ast::Expression* ExprFromDouble(ProgramBuilder& b, double v) {
        return Expr(b, Vector<Scalar, 1>{static_cast<ElementType>(v)});
    }
    /// @returns the WGSL name for the type
    static inline std::string Name() {
        return "array<" + DataType<T>::Name() + ", " + std::to_string(N) + ">";
    }
};

/// Helper for building atomic types and expressions
template <typename T>
struct DataType<core::fluent_types::atomic<T>> {
    /// The element type
    using ElementType = typename DataType<T>::ElementType;

    /// true as atomics are a composite type
    static constexpr bool is_composite = true;

    /// @param b the ProgramBuilder
    /// @return a new AST atomic type
    static inline ast::Type AST(ProgramBuilder& b) { return b.ty.atomic(DataType<T>::AST(b)); }

    /// @param b the ProgramBuilder
    /// @return the semantic atomic type
    static inline const core::type::Type* Sem(ProgramBuilder& b) {
        return b.Types().atomic(DataType<T>::Sem(b));
    }

    /// @returns the WGSL name for the type
    static inline std::string Name() { return "atomic<" + DataType<T>::Name() + ">"; }
};

/// Struct of all creation pointer types
struct CreatePtrs {
    /// ast node type create function
    ast_type_func_ptr ast;
    /// ast expression type create function
    ast_expr_func_ptr expr;
    /// ast expression type create function from double arg
    ast_expr_from_double_func_ptr expr_from_double;
    /// sem type create function
    sem_type_func_ptr sem;
    /// type name function
    type_name_func_ptr name;
};

/// @param o the std::ostream to write to
/// @param ptrs the CreatePtrs
/// @return the std::ostream so calls can be chained
inline std::ostream& operator<<(std::ostream& o, const CreatePtrs& ptrs) {
    return o << (ptrs.name ? ptrs.name() : "<unknown>");
}

/// Returns a CreatePtrs struct instance with all creation pointer types for
/// type `T`
template <typename T>
constexpr CreatePtrs CreatePtrsFor() {
    return {DataType<T>::AST, DataType<T>::Expr, DataType<T>::ExprFromDouble, DataType<T>::Sem,
            DataType<T>::Name};
}

/// True if DataType<T> is specialized for T, false otherwise.
template <typename T>
const bool IsDataTypeSpecializedFor =
    !std::is_same_v<typename DataType<T>::ElementType, UnspecializedElementType>;

/// Value is used to create Values with a Scalar vector initializer.
struct Value {
    /// Creates a Value for type T initialized with `args`
    /// @param args the scalar args
    /// @returns Value
    template <typename T>
    static Value Create(VectorRef<Scalar> args) {
        static_assert(IsDataTypeSpecializedFor<T>, "No DataType<T> specialization exists");
        using EL_TY = typename builder::DataType<T>::ElementType;
        return Value{
            std::move(args),          //
            CreatePtrsFor<T>(),       //
            core::IsAbstract<EL_TY>,  //
            core::IsIntegral<EL_TY>,  //
            core::FriendlyName<EL_TY>(),
        };
    }

    /// Creates an `ast::Expression` for the type T passing in previously stored args
    /// @param b the ProgramBuilder
    /// @returns an expression node
    const ast::Expression* Expr(ProgramBuilder& b) const { return (*create_ptrs.expr)(b, args); }

    /// Prints this value to the output stream
    /// @param o the output stream
    /// @returns input argument `o`
    std::ostream& Print(std::ostream& o) const {
        o << type_name << "(";
        for (auto& a : args) {
            o << a;
            if (&a != &args.Back()) {
                o << ", ";
            }
        }
        o << ")";
        return o;
    }

    /// The arguments used to construct the value
    Vector<Scalar, 4> args;
    /// CreatePtrs for value's type used to create an expression with `args`
    builder::CreatePtrs create_ptrs;
    /// True if the element type is abstract
    bool is_abstract = false;
    /// True if the element type is an integer
    bool is_integral = false;
    /// The name of the type.
    const char* type_name = "<invalid>";
};

/// Prints Value to ostream
inline std::ostream& operator<<(std::ostream& o, const Value& value) {
    return value.Print(o);
}

/// True if T is Value, false otherwise
template <typename T>
constexpr bool IsValue = std::is_same_v<T, Value>;

/// Creates a Value of DataType<T> from a scalar `v`
template <typename T>
Value Val(T v) {
    static_assert(tint::traits::IsTypeIn<T, Scalar::Value>, "v must be a Number of bool");
    return Value::Create<T>(Vector<Scalar, 1>{v});
}

/// Creates a Value of DataType<vec<N, T>> from N scalar `args`
template <typename... Ts>
Value Vec(Ts... args) {
    using FirstT = std::tuple_element_t<0, std::tuple<Ts...>>;
    static_assert(sizeof...(args) >= 2 && sizeof...(args) <= 4, "Invalid vector size");
    static_assert(std::conjunction_v<std::is_same<FirstT, Ts>...>,
                  "Vector args must all be the same type");
    constexpr size_t N = sizeof...(args);
    Vector<Scalar, sizeof...(args)> v{args...};
    return Value::Create<core::fluent_types::vec<N, FirstT>>(std::move(v));
}

/// Creates a Value of DataType<array<N, T>> from N scalar `args`
template <typename... Ts>
Value Array(Ts... args) {
    using FirstT = std::tuple_element_t<0, std::tuple<Ts...>>;
    static_assert(std::conjunction_v<std::is_same<FirstT, Ts>...>,
                  "Array args must all be the same type");
    constexpr size_t N = sizeof...(args);
    Vector<Scalar, sizeof...(args)> v{args...};
    return Value::Create<core::fluent_types::array<FirstT, N>>(std::move(v));
}

/// Creates a Value of DataType<mat<C,R,T> from C*R scalar `args`
template <size_t C, size_t R, typename T>
Value Mat(const T (&m_in)[C][R]) {
    Vector<Scalar, C * R> m;
    for (uint32_t i = 0; i < C; ++i) {
        for (size_t j = 0; j < R; ++j) {
            m.Push(m_in[i][j]);
        }
    }
    return Value::Create<core::fluent_types::mat<C, R, T>>(std::move(m));
}

/// Creates a Value of DataType<mat<2,R,T> from column vectors `c0` and `c1`
template <typename T, size_t R>
Value Mat(const T (&c0)[R], const T (&c1)[R]) {
    constexpr size_t C = 2;
    Vector<Scalar, C * R> m;
    for (auto v : c0) {
        m.Push(v);
    }
    for (auto v : c1) {
        m.Push(v);
    }
    return Value::Create<core::fluent_types::mat<C, R, T>>(std::move(m));
}

/// Creates a Value of DataType<mat<3,R,T> from column vectors `c0`, `c1`, and `c2`
template <typename T, size_t R>
Value Mat(const T (&c0)[R], const T (&c1)[R], const T (&c2)[R]) {
    constexpr size_t C = 3;
    Vector<Scalar, C * R> m;
    for (auto v : c0) {
        m.Push(v);
    }
    for (auto v : c1) {
        m.Push(v);
    }
    for (auto v : c2) {
        m.Push(v);
    }
    return Value::Create<core::fluent_types::mat<C, R, T>>(std::move(m));
}

/// Creates a Value of DataType<mat<4,R,T> from column vectors `c0`, `c1`, `c2`, and `c3`
template <typename T, size_t R>
Value Mat(const T (&c0)[R], const T (&c1)[R], const T (&c2)[R], const T (&c3)[R]) {
    constexpr size_t C = 4;
    Vector<Scalar, C * R> m;
    for (auto v : c0) {
        m.Push(v);
    }
    for (auto v : c1) {
        m.Push(v);
    }
    for (auto v : c2) {
        m.Push(v);
    }
    for (auto v : c3) {
        m.Push(v);
    }
    return Value::Create<core::fluent_types::mat<C, R, T>>(std::move(m));
}
}  // namespace builder
}  // namespace tint::resolver

#endif  // SRC_TINT_LANG_WGSL_RESOLVER_RESOLVER_HELPER_TEST_H_
