1 /**
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ES2PANDA_IR_TYPED_H
17 #define ES2PANDA_IR_TYPED_H
18 
19 #include "ir/astNode.h"
20 #include "ir/statement.h"
21 
22 namespace ark::es2panda::checker {
23 // NOLINTBEGIN(readability-redundant-declaration)
24 bool IsTypeError(Type const *tp);
25 [[noreturn]] void ThrowEmptyError();
26 // NOLINTEND(readability-redundant-declaration)
27 }  // namespace ark::es2panda::checker
28 
29 namespace ark::es2panda::ir {
30 
31 template <typename T>
32 class Typed : public T {
33 public:
34     Typed() = delete;
35     ~Typed() override = default;
36 
37     NO_COPY_OPERATOR(Typed);
38     NO_MOVE_SEMANTIC(Typed);
39 
TsType() const40     [[nodiscard]] checker::Type const *TsType() const
41     {
42         if (UNLIKELY(IsTypeError(tsType_))) {
43             checker::ThrowEmptyError();
44         }
45         return tsType_;
46     }
47 
48     [[nodiscard]] checker::Type const *TsTypeOrError() const noexcept
49     {
50         return tsType_;
51     }
52 
TsType()53     [[nodiscard]] checker::Type *TsType()
54     {
55         if (UNLIKELY(IsTypeError(tsType_))) {
56             checker::ThrowEmptyError();
57         }
58         return tsType_;
59     }
60 
61     [[nodiscard]] checker::Type *TsTypeOrError() noexcept
62     {
63         return tsType_;
64     }
65 
66     void SetTsType(checker::Type *tsType) noexcept
67     {
68         tsType_ = tsType;
69     }
70 
71     bool IsTyped() const override
72     {
73         return true;
74     }
75 
76 protected:
Typed(AstNodeType const type)77     explicit Typed(AstNodeType const type) : T(type) {}
Typed(AstNodeType const type, ModifierFlags const flags)78     explicit Typed(AstNodeType const type, ModifierFlags const flags) : T(type, flags) {}
79 
80     // NOTE: when cloning node its type is not copied but removed empty so that it can be re-checked further.
Typed(Typed const &other)81     Typed(Typed const &other) : T(static_cast<T const &>(other)) {}
82 
83 private:
84     checker::Type *tsType_ {};
85 };
86 
87 class TypedAstNode : public Typed<AstNode> {
88 public:
89     TypedAstNode() = delete;
90     ~TypedAstNode() override = default;
91 
92     NO_COPY_OPERATOR(TypedAstNode);
93     NO_MOVE_SEMANTIC(TypedAstNode);
94 
95 protected:
TypedAstNode(AstNodeType const type)96     explicit TypedAstNode(AstNodeType const type) : Typed<AstNode>(type) {}
TypedAstNode(AstNodeType const type, ModifierFlags const flags)97     explicit TypedAstNode(AstNodeType const type, ModifierFlags const flags) : Typed<AstNode>(type, flags) {}
98 
TypedAstNode(TypedAstNode const &other)99     TypedAstNode(TypedAstNode const &other) : Typed<AstNode>(static_cast<Typed<AstNode> const &>(other)) {}
100 };
101 
102 class AnnotatedAstNode : public Annotated<AstNode> {
103 public:
104     AnnotatedAstNode() = delete;
105     ~AnnotatedAstNode() override = default;
106 
107     NO_COPY_OPERATOR(AnnotatedAstNode);
108     NO_MOVE_SEMANTIC(AnnotatedAstNode);
109 
110 protected:
AnnotatedAstNode(AstNodeType const type, TypeNode *const typeAnnotation)111     explicit AnnotatedAstNode(AstNodeType const type, TypeNode *const typeAnnotation)
112         : Annotated<AstNode>(type, typeAnnotation)
113     {
114     }
AnnotatedAstNode(AstNodeType const type)115     explicit AnnotatedAstNode(AstNodeType const type) : Annotated<AstNode>(type) {}
AnnotatedAstNode(AstNodeType const type, ModifierFlags const flags)116     explicit AnnotatedAstNode(AstNodeType const type, ModifierFlags const flags) : Annotated<AstNode>(type, flags) {}
117 
AnnotatedAstNode(AnnotatedAstNode const &other)118     AnnotatedAstNode(AnnotatedAstNode const &other) : Annotated<AstNode>(static_cast<Annotated<AstNode> const &>(other))
119     {
120     }
121 };
122 
123 class TypedStatement : public Typed<Statement> {
124 public:
125     TypedStatement() = delete;
126     ~TypedStatement() override = default;
127 
128     NO_COPY_OPERATOR(TypedStatement);
129     NO_MOVE_SEMANTIC(TypedStatement);
130 
131 protected:
TypedStatement(AstNodeType type)132     explicit TypedStatement(AstNodeType type) : Typed<Statement>(type) {};
TypedStatement(AstNodeType type, ModifierFlags flags)133     explicit TypedStatement(AstNodeType type, ModifierFlags flags) : Typed<Statement>(type, flags) {};
134 
TypedStatement(TypedStatement const &other)135     TypedStatement(TypedStatement const &other) : Typed<Statement>(static_cast<Typed<Statement> const &>(other)) {}
136 
137     inline static checker::Type *const CHECKED = reinterpret_cast<checker::Type *>(0x01);
138 };
139 
140 class AnnotatedStatement : public Annotated<Statement> {
141 public:
142     AnnotatedStatement() = delete;
143     ~AnnotatedStatement() override = default;
144 
145     NO_COPY_OPERATOR(AnnotatedStatement);
146     NO_MOVE_SEMANTIC(AnnotatedStatement);
147 
148 protected:
AnnotatedStatement(AstNodeType type, TypeNode *typeAnnotation)149     explicit AnnotatedStatement(AstNodeType type, TypeNode *typeAnnotation) : Annotated<Statement>(type, typeAnnotation)
150     {
151     }
152 
AnnotatedStatement(AstNodeType type)153     explicit AnnotatedStatement(AstNodeType type) : Annotated<Statement>(type) {}
AnnotatedStatement(AstNodeType type, ModifierFlags flags)154     explicit AnnotatedStatement(AstNodeType type, ModifierFlags flags) : Annotated<Statement>(type, flags) {}
155 
AnnotatedStatement(AnnotatedStatement const &other)156     AnnotatedStatement(AnnotatedStatement const &other)
157         : Annotated<Statement>(static_cast<Annotated<Statement> const &>(other))
158     {
159     }
160 };
161 
162 }  // namespace ark::es2panda::ir
163 
164 #endif
165