tan  0.0.1
type.h
1 #ifndef __TAN_SRC_AST_TYPE_H__
2 #define __TAN_SRC_AST_TYPE_H__
3 #include "ast_base.h"
4 #include "fwd.h"
5 
6 namespace tanlang {
7 
8 class StringType;
9 class PrimitiveType;
10 class PointerType;
11 class ArrayType;
12 class TypeRef;
13 class StructType;
14 class StructDecl;
15 class FunctionType;
16 
17 /**
18  * \brief Type is immutable once created.
19  * The exception is StructType. Its information is updated in multiple semantic analysis stages.
20  * We make sure that GetXXType() doesn't create duplicated instances of the same type.
21  */
22 class Type {
23 public:
24  [[nodiscard]] static PrimitiveType *GetVoidType();
25  [[nodiscard]] static PrimitiveType *GetBoolType();
26  [[nodiscard]] static PrimitiveType *GetCharType();
27  [[nodiscard]] static PrimitiveType *GetIntegerType(size_t bit_size, bool is_unsigned);
28  [[nodiscard]] static PrimitiveType *GetFloatType(size_t bit_size);
29 
30  [[nodiscard]] static StringType *GetStringType();
31  [[nodiscard]] static PointerType *GetPointerType(Type *pointee);
32  [[nodiscard]] static ArrayType *GetArrayType(Type *element_type, int size);
33 
34  [[nodiscard]] static FunctionType *GetFunctionType(Type *ret_type, const vector<Type *> &arg_types);
35  [[nodiscard]] static StructType *GetStructType(StructDecl *decl);
36  [[nodiscard]] static TypeRef *GetTypeRef(const str &name);
37 
38  static inline vector<str> ALL_TYPE_NAMES{"bool", "int", "float", "f32", "str", "char", "f64", "i8",
39  "u8", "i16", "u16", "i32", "u32", "i64", "u64", "void"};
40 
41  /**
42  * \brief A composite type is canonical only if its subtype(s) are also canonical.
43  * A non-composite type is canonical only if it's not a type reference.
44  * \details We write it as a static method to check for infinite recursion using iterative search.
45  */
46  static bool IsCanonical(const Type &type);
47 
48 public:
49  virtual ~Type() = default;
50 
51  [[nodiscard]] virtual bool is_primitive() const;
52  [[nodiscard]] virtual bool is_pointer() const;
53  [[nodiscard]] virtual bool is_array() const;
54  [[nodiscard]] virtual bool is_string() const;
55  [[nodiscard]] virtual bool is_struct() const;
56  [[nodiscard]] virtual bool is_function() const;
57  [[nodiscard]] virtual bool is_ref() const;
58  [[nodiscard]] virtual bool is_float() const;
59  [[nodiscard]] virtual bool is_int() const;
60  [[nodiscard]] virtual bool is_num() const;
61  [[nodiscard]] virtual bool is_unsigned() const;
62  [[nodiscard]] virtual bool is_bool() const;
63  [[nodiscard]] virtual bool is_void() const;
64  [[nodiscard]] virtual bool is_char() const;
65 
66  virtual int get_align_bits();
67  virtual int get_size_bits();
68 
69  [[nodiscard]] virtual vector<Type *> children() const;
70  [[nodiscard]] bool is_canonical() const;
71  [[nodiscard]] const str &get_typename() const { return _type_name; }
72 
73 protected:
74  Type() = default;
75 
76 protected:
77  str _type_name{};
78 
79  // type cache
80  static StringType *STRING_TYPE;
81  static inline umap<Type *, PointerType *> POINTER_TYPE_CACHE{}; // pointee type -> pointer type
82  static inline umap<pair<Type *, int>, ArrayType *, PairHash> ARRAY_TYPE_CACHE{}; // (element type, size) -> array type
83  static inline umap<str, Type *> NAMED_TYPE_CACHE{}; // name -> type
84 };
85 
86 class PrimitiveType : public Type {
87 public:
88  enum Kind {
89  VOID,
90  BOOL,
91  I8,
92  I16,
93  I32,
94  I64,
95  CHAR,
96  U8,
97  U16,
98  U32,
99  U64,
100  F32,
101  F64,
102  };
103  static inline umap<Kind, int> SIZE_BITS{
104  {VOID, 0 },
105  {CHAR, 8 },
106  {I8, 8 },
107  {I16, 16},
108  {I32, 32},
109  {I64, 64},
110  {U8, 8 },
111  {U16, 16},
112  {U32, 32},
113  {U64, 64},
114  {F32, 32},
115  {F64, 64}
116  };
117  static inline umap<Kind, str> TYPE_NAMES{
118  {VOID, "void"},
119  {CHAR, "char"},
120  {I8, "i8" },
121  {I16, "i16" },
122  {I32, "i32" },
123  {I64, "i64" },
124  {U8, "u8" },
125  {U16, "u16" },
126  {U32, "u32" },
127  {U64, "u64" },
128  {F32, "f32" },
129  {F64, "f64" }
130  };
131  static const inline umap<str, Kind> TYPENAME_TO_KIND = {
132  {"int", I32 },
133  {"i8", I8 },
134  {"u8", U8 },
135  {"i16", I16 },
136  {"u16", U16 },
137  {"i32", I32 },
138  {"u32", U32 },
139  {"i64", I64 },
140  {"u64", U64 },
141  {"float", F32 },
142  {"f32", F32 },
143  {"f64", F64 },
144  {"void", VOID},
145  {"char", CHAR},
146  {"bool", BOOL}
147  };
148 
149 public:
150  [[nodiscard]] static PrimitiveType *Create(Kind kind);
151 
152  [[nodiscard]] bool is_primitive() const override { return true; }
153  [[nodiscard]] bool is_float() const override { return _kind == F32 || _kind == F64; }
154  [[nodiscard]] bool is_int() const override { return _kind >= I8 && _kind <= U64; }
155  [[nodiscard]] bool is_num() const override { return _kind >= I8 && _kind <= F64; }
156  [[nodiscard]] bool is_unsigned() const override { return _kind >= CHAR && _kind <= U64; };
157  [[nodiscard]] bool is_bool() const override { return _kind == BOOL; }
158  [[nodiscard]] bool is_void() const override { return _kind == VOID; }
159  [[nodiscard]] bool is_char() const override { return _kind == CHAR; }
160  [[nodiscard]] vector<Type *> children() const override { return {}; }
161 
162  int get_align_bits() override;
163  int get_size_bits() override;
164 
165 protected:
166  PrimitiveType() = default;
167 
168 private:
169  static inline umap<PrimitiveType::Kind, PrimitiveType *> CACHE{};
170 
171  Kind _kind;
172 };
173 
174 class PointerType : public Type {
175 public:
176  [[nodiscard]] bool is_pointer() const override { return true; }
177  Type *get_pointee() { return _pointee_type; }
178  int get_align_bits() override;
179  int get_size_bits() override;
180  [[nodiscard]] vector<Type *> children() const override;
181 
182  friend class Type;
183 
184 protected:
185  explicit PointerType(Type *pointee_type);
186 
187 private:
188  Type *_pointee_type = nullptr;
189 };
190 
191 class ArrayType : public Type {
192 public:
193  Type *get_element_type() { return _element_type; }
194  int array_size() { return _size; }
195  [[nodiscard]] bool is_array() const override { return true; }
196  int get_align_bits() override;
197  int get_size_bits() override;
198  [[nodiscard]] vector<Type *> children() const override;
199 
200  friend class Type;
201 
202 protected:
203  ArrayType(Type *element_type, int size);
204 
205 private:
206  Type *_element_type = nullptr;
207  int _size = 0;
208 };
209 
210 class StringType : public Type {
211 public:
212  [[nodiscard]] bool is_string() const override { return true; }
213  int get_align_bits() override;
214  int get_size_bits() override;
215  [[nodiscard]] vector<Type *> children() const override { return {}; }
216 
217  friend class Type;
218 
219 protected:
220  StringType();
221 };
222 
223 class StructType : public Type {
224 public:
225  [[nodiscard]] bool is_struct() const override { return true; }
226  [[nodiscard]] vector<Type *> get_member_types() const;
227  int get_align_bits() override;
228  int get_size_bits() override;
229  [[nodiscard]] vector<Type *> children() const override;
230  StructDecl *get_decl() const;
231 
232  void append_member_type(Type *t);
233  Type *&operator[](size_t index);
234  Type *operator[](size_t index) const;
235 
236  friend class Type;
237 
238 protected:
239  StructType(StructDecl *decl);
240 
241 private:
242  vector<Type *> _member_types{};
243  StructDecl *_decl = nullptr;
244 };
245 
246 class FunctionType : public Type {
247 public:
248  [[nodiscard]] bool is_function() const override { return true; }
249  [[nodiscard]] Type *get_return_type() const;
250  void set_return_type(Type *t);
251  [[nodiscard]] vector<Type *> get_arg_types() const;
252  void set_arg_types(const vector<Type *> &arg_types);
253  [[nodiscard]] vector<Type *> children() const override;
254 
255  friend class Type;
256 
257 protected:
258  FunctionType(Type *ret_type, const vector<Type *> &arg_types);
259 
260 private:
261  Type *_ret_type = nullptr;
262  vector<Type *> _arg_types{};
263 };
264 
265 /**
266  * \brief Placeholder during parsing
267  */
268 class TypeRef : public Type {
269 public:
270  friend class Type;
271  [[nodiscard]] bool is_ref() const override { return true; }
272  [[nodiscard]] vector<Type *> children() const override { return {}; }
273 
274 protected:
275  explicit TypeRef(const str &name);
276 };
277 
278 } // namespace tanlang
279 
280 #endif //__TAN_SRC_AST_TYPE_H__
Placeholder during parsing.
Definition: type.h:268
Type is immutable once created. The exception is StructType. Its information is updated in multiple s...
Definition: type.h:22
static bool IsCanonical(const Type &type)
A composite type is canonical only if its subtype(s) are also canonical. A non-composite type is cano...
Definition: type.cpp:209