ast: Migrate all nodes over to typ::*

(except for ast::Module)

CloneContext::Clone(typ::Type) now only clones the sem::Type. Attempting
to clone both the AST and SEM type will cause the cloned AST to be
disjoint. Another change will switch this over to cloning the AST.

Bug: tint:724
Change-Id: I2baf5491365d7dc25e6b25d02bfbb46bf90fd0d9
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/49341
Commit-Queue: Ben Clayton <bclayton@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
Ben Clayton 2021-04-28 09:29:13 +00:00 committed by Commit Bot service account
parent 70c8a96cd8
commit 761e6b139c
23 changed files with 55 additions and 68 deletions

View File

@ -23,10 +23,10 @@ namespace ast {
BitcastExpression::BitcastExpression(ProgramID program_id, BitcastExpression::BitcastExpression(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
Expression* expr) Expression* expr)
: Base(program_id, source), type_(type), expr_(expr) { : Base(program_id, source), type_(type), expr_(expr) {
TINT_ASSERT(type_); TINT_ASSERT(type_.sem);
TINT_ASSERT(expr_); TINT_ASSERT(expr_);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(expr, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(expr, program_id);
} }
@ -37,7 +37,7 @@ BitcastExpression::~BitcastExpression() = default;
BitcastExpression* BitcastExpression::Clone(CloneContext* ctx) const { BitcastExpression* BitcastExpression::Clone(CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source()); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type()); auto ty = ctx->Clone(type());
auto* e = ctx->Clone(expr_); auto* e = ctx->Clone(expr_);
return ctx->dst->create<BitcastExpression>(src, ty, e); return ctx->dst->create<BitcastExpression>(src, ty, e);
} }

View File

@ -30,14 +30,14 @@ class BitcastExpression : public Castable<BitcastExpression, Expression> {
/// @param expr the expr /// @param expr the expr
BitcastExpression(ProgramID program_id, BitcastExpression(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
Expression* expr); Expression* expr);
/// Move constructor /// Move constructor
BitcastExpression(BitcastExpression&&); BitcastExpression(BitcastExpression&&);
~BitcastExpression() override; ~BitcastExpression() override;
/// @returns the left side expression /// @returns the left side expression
sem::Type* type() const { return const_cast<sem::Type*>(type_); } typ::Type type() const { return type_; }
/// @returns the expression /// @returns the expression
Expression* expr() const { return expr_; } Expression* expr() const { return expr_; }
@ -58,7 +58,7 @@ class BitcastExpression : public Castable<BitcastExpression, Expression> {
private: private:
BitcastExpression(const BitcastExpression&) = delete; BitcastExpression(const BitcastExpression&) = delete;
const sem::Type* const type_; typ::Type const type_;
Expression* const expr_; Expression* const expr_;
}; };

View File

@ -23,7 +23,7 @@ namespace ast {
BoolLiteral::BoolLiteral(ProgramID program_id, BoolLiteral::BoolLiteral(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
bool value) bool value)
: Base(program_id, source, type), value_(value) {} : Base(program_id, source, type), value_(value) {}
@ -40,7 +40,7 @@ std::string BoolLiteral::name() const {
BoolLiteral* BoolLiteral::Clone(CloneContext* ctx) const { BoolLiteral* BoolLiteral::Clone(CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source()); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type()); auto ty = ctx->Clone(type());
return ctx->dst->create<BoolLiteral>(src, ty, value_); return ctx->dst->create<BoolLiteral>(src, ty, value_);
} }

View File

@ -32,7 +32,7 @@ class BoolLiteral : public Castable<BoolLiteral, Literal> {
/// @param value the bool literals value /// @param value the bool literals value
BoolLiteral(ProgramID program_id, BoolLiteral(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
bool value); bool value);
~BoolLiteral() override; ~BoolLiteral() override;

View File

@ -21,24 +21,21 @@ namespace {
using BoolLiteralTest = TestHelper; using BoolLiteralTest = TestHelper;
TEST_F(BoolLiteralTest, True) { TEST_F(BoolLiteralTest, True) {
sem::Bool bool_type; auto* b = create<BoolLiteral>(ty.bool_(), true);
auto* b = create<BoolLiteral>(&bool_type, true);
ASSERT_TRUE(b->Is<BoolLiteral>()); ASSERT_TRUE(b->Is<BoolLiteral>());
ASSERT_TRUE(b->IsTrue()); ASSERT_TRUE(b->IsTrue());
ASSERT_FALSE(b->IsFalse()); ASSERT_FALSE(b->IsFalse());
} }
TEST_F(BoolLiteralTest, False) { TEST_F(BoolLiteralTest, False) {
sem::Bool bool_type; auto* b = create<BoolLiteral>(ty.bool_(), false);
auto* b = create<BoolLiteral>(&bool_type, false);
ASSERT_TRUE(b->Is<BoolLiteral>()); ASSERT_TRUE(b->Is<BoolLiteral>());
ASSERT_FALSE(b->IsTrue()); ASSERT_FALSE(b->IsTrue());
ASSERT_TRUE(b->IsFalse()); ASSERT_TRUE(b->IsFalse());
} }
TEST_F(BoolLiteralTest, Is) { TEST_F(BoolLiteralTest, Is) {
sem::Bool bool_type; ast::Literal* l = create<BoolLiteral>(ty.bool_(), false);
ast::Literal* l = create<BoolLiteral>(&bool_type, false);
EXPECT_TRUE(l->Is<BoolLiteral>()); EXPECT_TRUE(l->Is<BoolLiteral>());
EXPECT_FALSE(l->Is<SintLiteral>()); EXPECT_FALSE(l->Is<SintLiteral>());
EXPECT_FALSE(l->Is<FloatLiteral>()); EXPECT_FALSE(l->Is<FloatLiteral>());
@ -47,9 +44,8 @@ TEST_F(BoolLiteralTest, Is) {
} }
TEST_F(BoolLiteralTest, ToStr) { TEST_F(BoolLiteralTest, ToStr) {
sem::Bool bool_type; auto* t = create<BoolLiteral>(ty.bool_(), true);
auto* t = create<BoolLiteral>(&bool_type, true); auto* f = create<BoolLiteral>(ty.bool_(), false);
auto* f = create<BoolLiteral>(&bool_type, false);
EXPECT_EQ(str(t), "true"); EXPECT_EQ(str(t), "true");
EXPECT_EQ(str(f), "false"); EXPECT_EQ(str(f), "false");

View File

@ -25,7 +25,7 @@ namespace ast {
FloatLiteral::FloatLiteral(ProgramID program_id, FloatLiteral::FloatLiteral(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
float value) float value)
: Base(program_id, source, type), value_(value) {} : Base(program_id, source, type), value_(value) {}
@ -46,7 +46,7 @@ std::string FloatLiteral::name() const {
FloatLiteral* FloatLiteral::Clone(CloneContext* ctx) const { FloatLiteral* FloatLiteral::Clone(CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source()); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type()); auto ty = ctx->Clone(type());
return ctx->dst->create<FloatLiteral>(src, ty, value_); return ctx->dst->create<FloatLiteral>(src, ty, value_);
} }

View File

@ -32,7 +32,7 @@ class FloatLiteral : public Castable<FloatLiteral, Literal> {
/// @param value the float literals value /// @param value the float literals value
FloatLiteral(ProgramID program_id, FloatLiteral(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
float value); float value);
~FloatLiteral() override; ~FloatLiteral() override;

View File

@ -21,7 +21,7 @@ namespace ast {
IntLiteral::IntLiteral(ProgramID program_id, IntLiteral::IntLiteral(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
uint32_t value) uint32_t value)
: Base(program_id, source, type), value_(value) {} : Base(program_id, source, type), value_(value) {}

View File

@ -36,7 +36,7 @@ class IntLiteral : public Castable<IntLiteral, Literal> {
/// @param value value of the literal /// @param value value of the literal
IntLiteral(ProgramID program_id, IntLiteral(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
uint32_t value); uint32_t value);
private: private:

View File

@ -19,9 +19,7 @@ TINT_INSTANTIATE_TYPEINFO(tint::ast::Literal);
namespace tint { namespace tint {
namespace ast { namespace ast {
Literal::Literal(ProgramID program_id, Literal::Literal(ProgramID program_id, const Source& source, typ::Type type)
const Source& source,
const sem::Type* type)
: Base(program_id, source), type_(type) {} : Base(program_id, source), type_(type) {}
Literal::~Literal() = default; Literal::~Literal() = default;

View File

@ -28,7 +28,7 @@ class Literal : public Castable<Literal, Node> {
~Literal() override; ~Literal() override;
/// @returns the type of the literal /// @returns the type of the literal
sem::Type* type() const { return const_cast<sem::Type*>(type_); } typ::Type type() const { return type_; }
/// Writes a representation of the node to the output stream /// Writes a representation of the node to the output stream
/// @param sem the semantic info for the program /// @param sem the semantic info for the program
@ -50,12 +50,10 @@ class Literal : public Castable<Literal, Node> {
/// @param program_id the identifier of the program that owns this node /// @param program_id the identifier of the program that owns this node
/// @param source the input source /// @param source the input source
/// @param type the type of the literal /// @param type the type of the literal
explicit Literal(ProgramID program_id, explicit Literal(ProgramID program_id, const Source& source, typ::Type type);
const Source& source,
const sem::Type* type);
private: private:
const sem::Type* const type_; typ::Type const type_;
}; };
} // namespace ast } // namespace ast

View File

@ -23,7 +23,7 @@ namespace ast {
SintLiteral::SintLiteral(ProgramID program_id, SintLiteral::SintLiteral(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
int32_t value) int32_t value)
: Base(program_id, source, type, static_cast<uint32_t>(value)) {} : Base(program_id, source, type, static_cast<uint32_t>(value)) {}
@ -40,7 +40,7 @@ std::string SintLiteral::name() const {
SintLiteral* SintLiteral::Clone(CloneContext* ctx) const { SintLiteral* SintLiteral::Clone(CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source()); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type()); auto ty = ctx->Clone(type());
return ctx->dst->create<SintLiteral>(src, ty, value()); return ctx->dst->create<SintLiteral>(src, ty, value());
} }

View File

@ -32,7 +32,7 @@ class SintLiteral : public Castable<SintLiteral, IntLiteral> {
/// @param value the signed int literals value /// @param value the signed int literals value
SintLiteral(ProgramID program_id, SintLiteral(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
int32_t value); int32_t value);
~SintLiteral() override; ~SintLiteral() override;

View File

@ -45,8 +45,7 @@ TEST_F(SintLiteralTest, Name_I32) {
} }
TEST_F(SintLiteralTest, Name_U32) { TEST_F(SintLiteralTest, Name_U32) {
sem::U32 u32; auto* i = create<SintLiteral>(ty.u32(), 2);
auto* i = create<SintLiteral>(&u32, 2);
EXPECT_EQ("__sint__u32_2", i->name()); EXPECT_EQ("__sint__u32_2", i->name());
} }

View File

@ -23,10 +23,10 @@ namespace ast {
TypeConstructorExpression::TypeConstructorExpression(ProgramID program_id, TypeConstructorExpression::TypeConstructorExpression(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
ExpressionList values) ExpressionList values)
: Base(program_id, source), type_(type), values_(std::move(values)) { : Base(program_id, source), type_(type), values_(std::move(values)) {
TINT_ASSERT(type_); TINT_ASSERT(type_.sem);
for (auto* val : values_) { for (auto* val : values_) {
TINT_ASSERT(val); TINT_ASSERT(val);
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(val, program_id); TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(val, program_id);
@ -42,7 +42,7 @@ TypeConstructorExpression* TypeConstructorExpression::Clone(
CloneContext* ctx) const { CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source()); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type()); auto ty = ctx->Clone(type());
auto vals = ctx->Clone(values()); auto vals = ctx->Clone(values());
return ctx->dst->create<TypeConstructorExpression>(src, ty, vals); return ctx->dst->create<TypeConstructorExpression>(src, ty, vals);
} }

View File

@ -33,14 +33,14 @@ class TypeConstructorExpression
/// @param values the constructor values /// @param values the constructor values
TypeConstructorExpression(ProgramID program_id, TypeConstructorExpression(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
ExpressionList values); ExpressionList values);
/// Move constructor /// Move constructor
TypeConstructorExpression(TypeConstructorExpression&&); TypeConstructorExpression(TypeConstructorExpression&&);
~TypeConstructorExpression() override; ~TypeConstructorExpression() override;
/// @returns the type /// @returns the type
sem::Type* type() const { return const_cast<sem::Type*>(type_); } typ::Type type() const { return type_; }
/// @returns the values /// @returns the values
const ExpressionList& values() const { return values_; } const ExpressionList& values() const { return values_; }
@ -62,7 +62,7 @@ class TypeConstructorExpression
private: private:
TypeConstructorExpression(const TypeConstructorExpression&) = delete; TypeConstructorExpression(const TypeConstructorExpression&) = delete;
const sem::Type* const type_; typ::Type const type_;
ExpressionList const values_; ExpressionList const values_;
}; };

View File

@ -81,13 +81,12 @@ TEST_F(TypeConstructorExpressionTest, Assert_DifferentProgramID_Value) {
} }
TEST_F(TypeConstructorExpressionTest, ToStr) { TEST_F(TypeConstructorExpressionTest, ToStr) {
sem::Vector vec(ty.f32(), 3);
ExpressionList expr; ExpressionList expr;
expr.push_back(Expr("expr_1")); expr.push_back(Expr("expr_1"));
expr.push_back(Expr("expr_2")); expr.push_back(Expr("expr_2"));
expr.push_back(Expr("expr_3")); expr.push_back(Expr("expr_3"));
auto* t = create<TypeConstructorExpression>(&vec, expr); auto* t = create<TypeConstructorExpression>(ty.vec3<f32>(), expr);
EXPECT_EQ(str(t), R"(TypeConstructor[not set]{ EXPECT_EQ(str(t), R"(TypeConstructor[not set]{
__vec_3__f32 __vec_3__f32
Identifier[not set]{expr_1} Identifier[not set]{expr_1}

View File

@ -23,7 +23,7 @@ namespace ast {
UintLiteral::UintLiteral(ProgramID program_id, UintLiteral::UintLiteral(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
uint32_t value) uint32_t value)
: Base(program_id, source, type, value) {} : Base(program_id, source, type, value) {}
@ -40,7 +40,7 @@ std::string UintLiteral::name() const {
UintLiteral* UintLiteral::Clone(CloneContext* ctx) const { UintLiteral* UintLiteral::Clone(CloneContext* ctx) const {
// Clone arguments outside of create() call to have deterministic ordering // Clone arguments outside of create() call to have deterministic ordering
auto src = ctx->Clone(source()); auto src = ctx->Clone(source());
auto* ty = ctx->Clone(type()); auto ty = ctx->Clone(type());
return ctx->dst->create<UintLiteral>(src, ty, value()); return ctx->dst->create<UintLiteral>(src, ty, value());
} }

View File

@ -32,7 +32,7 @@ class UintLiteral : public Castable<UintLiteral, IntLiteral> {
/// @param value the uint literals value /// @param value the uint literals value
UintLiteral(ProgramID program_id, UintLiteral(ProgramID program_id,
const Source& source, const Source& source,
const sem::Type* type, typ::Type type,
uint32_t value); uint32_t value);
~UintLiteral() override; ~UintLiteral() override;

View File

@ -185,8 +185,7 @@ class CloneContext {
/// @return the cloned type pair /// @return the cloned type pair
template <typename AST, typename SEM> template <typename AST, typename SEM>
typ::TypePair<AST, SEM> Clone(const typ::TypePair<AST, SEM>& tp) { typ::TypePair<AST, SEM> Clone(const typ::TypePair<AST, SEM>& tp) {
return {Clone(const_cast<ast::Type*>(tp.ast)), return Clone(const_cast<sem::Type*>(tp.sem));
Clone(const_cast<sem::Type*>(tp.sem))};
} }
/// Clones the Source `s` into #dst /// Clones the Source `s` into #dst

View File

@ -160,19 +160,19 @@ TEST_F(SpvNamerTest, RegisterWithoutId_Twice) {
// Fails on second attempt. // Fails on second attempt.
EXPECT_FALSE(namer.RegisterWithoutId(n)); EXPECT_FALSE(namer.RegisterWithoutId(n));
EXPECT_FALSE(success_); EXPECT_FALSE(success_);
EXPECT_EQ(error(),"internal error: name already registered: abbey"); EXPECT_EQ(error(), "internal error: name already registered: abbey");
} }
TEST_F(SpvNamerTest, RegisterWithoutId_ConflictsWithIdRegisteredName) { TEST_F(SpvNamerTest, RegisterWithoutId_ConflictsWithIdRegisteredName) {
Namer namer(fail_stream_); Namer namer(fail_stream_);
const std::string n("abbey"); const std::string n("abbey");
EXPECT_TRUE(namer.Register(1,n)); EXPECT_TRUE(namer.Register(1, n));
EXPECT_TRUE(namer.IsRegistered(n)); EXPECT_TRUE(namer.IsRegistered(n));
// Fails on attempt to register without ID. // Fails on attempt to register without ID.
EXPECT_FALSE(namer.RegisterWithoutId(n)); EXPECT_FALSE(namer.RegisterWithoutId(n));
EXPECT_FALSE(success_); EXPECT_FALSE(success_);
EXPECT_EQ(error(),"internal error: name already registered: abbey"); EXPECT_EQ(error(), "internal error: name already registered: abbey");
} }
TEST_F(SpvNamerTest, Register_Once) { TEST_F(SpvNamerTest, Register_Once) {

View File

@ -151,11 +151,9 @@ TEST_P(VecTest, Parse) {
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
ParserImplTest, ParserImplTest,
VecTest, VecTest,
testing::Values(VecData{"vec2<f32>", 2, Source::Range{{1u, 1u}, {1u, 10u}}}, testing::Values(VecData{"vec2<f32>", 2, {{1u, 1u}, {1u, 10u}}},
VecData{"vec3<f32>", 3, Source::Range{{1u, 1u}, {1u, 10u}}}, VecData{"vec3<f32>", 3, {{1u, 1u}, {1u, 10u}}},
VecData{"vec4<f32>", 4, Source::Range{{1u, 1u}, {1u, 10u}}} VecData{"vec4<f32>", 4, {{1u, 1u}, {1u, 10u}}}));
));
class VecMissingGreaterThanTest : public ParserImplTestWithParam<VecData> {}; class VecMissingGreaterThanTest : public ParserImplTestWithParam<VecData> {};
@ -657,16 +655,15 @@ TEST_P(MatrixTest, Parse) {
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
ParserImplTest, ParserImplTest,
MatrixTest, MatrixTest,
testing::Values( testing::Values(MatrixData{"mat2x2<f32>", 2, 2, {{1u, 1u}, {1u, 12u}}},
MatrixData{"mat2x2<f32>", 2, 2, Source::Range{{1u, 1u}, {1u, 12u}}}, MatrixData{"mat2x3<f32>", 2, 3, {{1u, 1u}, {1u, 12u}}},
MatrixData{"mat2x3<f32>", 2, 3, Source::Range{{1u, 1u}, {1u, 12u}}}, MatrixData{"mat2x4<f32>", 2, 4, {{1u, 1u}, {1u, 12u}}},
MatrixData{"mat2x4<f32>", 2, 4, Source::Range{{1u, 1u}, {1u, 12u}}}, MatrixData{"mat3x2<f32>", 3, 2, {{1u, 1u}, {1u, 12u}}},
MatrixData{"mat3x2<f32>", 3, 2, Source::Range{{1u, 1u}, {1u, 12u}}}, MatrixData{"mat3x3<f32>", 3, 3, {{1u, 1u}, {1u, 12u}}},
MatrixData{"mat3x3<f32>", 3, 3, Source::Range{{1u, 1u}, {1u, 12u}}}, MatrixData{"mat3x4<f32>", 3, 4, {{1u, 1u}, {1u, 12u}}},
MatrixData{"mat3x4<f32>", 3, 4, Source::Range{{1u, 1u}, {1u, 12u}}}, MatrixData{"mat4x2<f32>", 4, 2, {{1u, 1u}, {1u, 12u}}},
MatrixData{"mat4x2<f32>", 4, 2, Source::Range{{1u, 1u}, {1u, 12u}}}, MatrixData{"mat4x3<f32>", 4, 3, {{1u, 1u}, {1u, 12u}}},
MatrixData{"mat4x3<f32>", 4, 3, Source::Range{{1u, 1u}, {1u, 12u}}}, MatrixData{"mat4x4<f32>", 4, 4, {{1u, 1u}, {1u, 12u}}}));
MatrixData{"mat4x4<f32>", 4, 4, Source::Range{{1u, 1u}, {1u, 12u}}}));
class MatrixMissingGreaterThanTest class MatrixMissingGreaterThanTest
: public ParserImplTestWithParam<MatrixData> {}; : public ParserImplTestWithParam<MatrixData> {};

View File

@ -101,7 +101,6 @@ struct TypePair {
sem(static_cast<const SEM*>(other.sem)) {} sem(static_cast<const SEM*>(other.sem)) {}
/// Constructor /// Constructor
/// @param a the ast::Type pointer /// @param a the ast::Type pointer
template <typename U>
TypePair(const AST* a) : ast(a) {} // NOLINT: explicit TypePair(const AST* a) : ast(a) {} // NOLINT: explicit
/// Constructor /// Constructor
/// @param s the sem::Type pointer /// @param s the sem::Type pointer
@ -110,6 +109,8 @@ struct TypePair {
/// @param a the ast::Type pointer /// @param a the ast::Type pointer
/// @param s the sem::Type pointer /// @param s the sem::Type pointer
TypePair(const AST* a, const SEM* s) : ast(a), sem(s) {} TypePair(const AST* a, const SEM* s) : ast(a), sem(s) {}
/// Constructor
TypePair(std::nullptr_t) {} // NOLINT: explicit
/// @returns the ast::Type pointer /// @returns the ast::Type pointer
operator AST*() const { return const_cast<AST*>(ast); } operator AST*() const { return const_cast<AST*>(ast); }