Yume
ast.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "token.hpp"
5#include "ty/type_base.hpp"
6#include "util.hpp"
7#include <concepts>
8#include <cstdint>
9#include <llvm/ADT/SmallPtrSet.h>
10#include <llvm/Support/ErrorHandling.h>
11#include <memory>
12#include <optional>
13#include <span>
14#include <string>
15#include <unordered_set>
16#include <utility>
17#include <variant>
18#include <vector>
19
20namespace llvm {
21class Function;
22}
23
24namespace yume {
25class Visitor;
26struct Fn;
27enum struct Qualifier;
28namespace diagnostic {
29struct NotesHolder;
30}
31} // namespace yume
32
33namespace yume::ast {
34
35enum Kind {
36 K_Unknown, ///< Unknown, default, zero value. Hopefully never encountered!
37 K_IfClause, ///< `IfClause`
38 K_TypeName, ///< `TypeName`
39 K_GenericParam, ///< `GenericParam`
40
41 /** subclasses of Stmt */
42 /**/ K_Stmt, ///< `Stmt`
43 /**/ K_Compound, ///< `Compound`
44 /**/ K_While, ///< `WhileStmt`
45 /**/ K_If, ///< `IfStmt`
46 /**/ K_Return, ///< `ReturnStmt`
47 /**/ K_Program, ///< `Program`
48
49 /**** subclasses of Decl */
50 /****/ K_Decl, ///< `Decl`
51 /****/ K_FnDecl, ///< `FnDecl`
52 /****/ K_CtorDecl, ///< `CtorDecl`
53 /****/ K_StructDecl, ///< `StructDecl`
54 /****/ K_VarDecl, ///< `VarDecl`
55 /****/ K_ConstDecl, ///< `ConstDecl`
56 /****/ K_END_Decl,
57
58 /**** subclasses of Expr */
59 /****/ K_Expr, ///< `Expr`
60 /****/ K_Number, ///< `NumberExpr`
61 /****/ K_Char, ///< `CharExpr`
62 /****/ K_Bool, ///< `BoolExpr`
63 /****/ K_String, ///< `StringExpr`
64 /****/ K_Var, ///< `VarExpr`
65 /****/ K_Const, ///< `ConstExpr`
66 /****/ K_Call, ///< `CallExpr`
67 /****/ K_BinaryLogic, ///< `BinaryLogicExpr`
68 /****/ K_Ctor, ///< `CtorExpr`
69 /****/ K_Dtor, ///< `DtorExpr`
70 /****/ K_Slice, ///< `SliceExpr`
71 /****/ K_Lambda, ///< `LambdaExpr`
72 /****/ K_Assign, ///< `AssignExpr`
73 /****/ K_FieldAccess, ///< `FieldAccessExpr`
74 /****/ K_ImplicitCast, ///< `ImplicitCastExpr`
75 /****/ K_TypeExpr, ///< `TypeExpr`
76 /****/ K_END_Expr,
78
79 /** subclasses of Type */
80 /**/ K_Type, ///< `Type`
81 /**/ K_SimpleType, ///< `SimpleType`
82 /**/ K_QualType, ///< `QualType`
83 /**/ K_TemplatedType, ///< `TemplatedType`
84 /**/ K_FunctionType, ///< `TemplatedType`
85 /**/ K_SelfType, ///< `SelfType`
86 /**/ K_ProxyType, ///< `ProxyType`
88};
89
90auto inline constexpr kind_name(Kind type) -> const char* {
91 switch (type) {
92 case K_Unknown: return "unknown";
93 case K_Number: return "number";
94 case K_String: return "string";
95 case K_Char: return "char";
96 case K_Bool: return "bool";
97 case K_FnDecl: return "fn-decl";
98 case K_CtorDecl: return "ctor-decl";
99 case K_VarDecl: return "var-decl";
100 case K_ConstDecl: return "const-decl";
101 case K_StructDecl: return "struct-decl";
102 case K_Program: return "program";
103 case K_SimpleType: return "simple-type";
104 case K_QualType: return "qual-type";
105 case K_TemplatedType: return "templated-type";
106 case K_FunctionType: return "function-type";
107 case K_SelfType: return "self-type";
108 case K_ProxyType: return "proxy-type";
109 case K_TypeName: return "type-name";
110 case K_GenericParam: return "generic-param";
111 case K_Compound: return "compound";
112 case K_While: return "while-statement";
113 case K_If: return "if-statement";
114 case K_IfClause: return "if-clause";
115 case K_Call: return "call";
116 case K_BinaryLogic: return "binary-logic";
117 case K_Ctor: return "constructor";
118 case K_Dtor: return "destructor";
119 case K_Slice: return "slice";
120 case K_Var: return "var";
121 case K_Const: return "const";
122 case K_Lambda: return "lambda";
123 case K_Return: return "return-statement";
124 case K_Assign: return "assign";
125 case K_FieldAccess: return "field-access";
126 case K_ImplicitCast: return "implicit-cast";
127 case K_TypeExpr: return "type-expr";
128
129 case K_Stmt:
130 case K_Expr:
131 case K_Type:
132 case K_Decl:
133 case K_END_Expr:
134 case K_END_Decl:
135 case K_END_Stmt:
136 case K_END_Type: llvm_unreachable("Invalid type name for ast node");
137 }
138}
139
140class TokenIterator;
141class AST;
142template <typename T> class AnyBase;
143
144/// Represents "any" kind of ast node of type `T`, or the absence of one. See `OptionalExpr` and `OptionalType`.
145/**
146 * This template exists to avoid passing around `unique_ptr<T>`s around in code that deals with AST nodes containing
147 * other generic nodes, such as `Compound`.
148 * This class has the exact same layout at `AnyBase`, but is nominally explicit in its semantics, in that it may be
149 * null. It replaces the earlier usages of `optional<unique_ptr<T>>` which in theory wastes memory for the "optional"
150 * part when a nullptr already expresses the desired semantics.
151 * Unlike `AnyBase`, this class does not perform null pointer checks, and may be default constructed, or constructed
152 * from a `nullptr`.
153 */
154template <typename T> class OptionalAnyBase {
155 unique_ptr<T> m_val;
156 friend AnyBase<T>;
157
158public:
159 OptionalAnyBase() : m_val() {}
160 explicit OptionalAnyBase(T* raw_ptr) : m_val{raw_ptr} {}
161 template <std::convertible_to<unique_ptr<T>> U> OptionalAnyBase(U uptr) : m_val{move(uptr)} {}
162 OptionalAnyBase(std::nullopt_t /* tag */) : m_val{} {}
163 explicit OptionalAnyBase(optional<unique_ptr<T>> opt_uptr)
164 : m_val{opt_uptr.has_value() ? move(*opt_uptr) : nullptr} {}
165
166 [[nodiscard]] auto operator->() const -> const T* { return m_val.operator->(); }
167 [[nodiscard]] auto operator*() const -> const T& { return *m_val; }
168 [[nodiscard]] auto operator->() -> T* { return m_val.operator->(); }
169 [[nodiscard]] auto operator*() -> T& { return *m_val; }
170
171 [[nodiscard]] operator bool() const { return static_cast<bool>(m_val); }
172 [[nodiscard]] auto has_value() const -> bool { return static_cast<bool>(m_val); }
173 [[nodiscard]] auto raw_ptr() const -> const T* { return m_val.get(); }
174 [[nodiscard]] auto raw_ptr() -> T* { return m_val.get(); }
175};
176
177/// Represents "any" kind of ast node of type `T`. See `AnyExpr`, `AnyStmt` and `AnyType`.
178/**
179 * This template exists to avoid passing around `unique_ptr<T>`s around in code that deals with AST nodes containing
180 * other generic nodes, such as `Compound`.
181 * This class also has strict nullptr checks when constructing, and cannot be default constructed. See
182 * `OptionalAnyBase` for a similar class which may be null.
183 */
184template <typename T> class AnyBase : public OptionalAnyBase<T> {
186
187public:
188 AnyBase() = delete;
189 explicit AnyBase(T* raw_ptr) : Super{raw_ptr} { YUME_ASSERT(raw_ptr != nullptr, "AnyBase should never be null"); }
190 template <std::convertible_to<unique_ptr<T>> U> AnyBase(U uptr) noexcept : Super{move(uptr)} {
191 YUME_ASSERT(Super::m_val.get() != nullptr, "AnyBase should never be null");
192 }
193 AnyBase(OptionalAnyBase<T>&& other) : Super(move(other.m_val)) {}
194
195 [[nodiscard]] auto operator->() const -> const T* { return Super::m_val.operator->(); }
196 [[nodiscard]] auto operator*() const -> const T& { return *Super::m_val; }
197 [[nodiscard]] auto operator->() -> T* { return Super::m_val.operator->(); }
198 [[nodiscard]] auto operator*() -> T& { return *Super::m_val; }
199
200 [[nodiscard]] auto raw_ptr() const -> const T* { return Super::m_val.get(); }
201 [[nodiscard]] auto raw_ptr() -> T* { return Super::m_val.get(); }
202};
203
204/// Represents the relationship between multiple `AST` nodes.
205/**
206 * `AST` nodes can be attached to propagate type information between them.
207 * TODO: describe type propagation more
208 */
210 /// Observers are the "children" and should have their type updated when this node's type changes
211 llvm::SmallPtrSet<AST*, 2> observers{};
212 /// Depends are the "parents" and should be verified for type compatibility when this node's type changes
213 llvm::SmallPtrSet<AST*, 2> depends{};
214};
215
216/// All nodes in the `AST` tree of the program inherit from this class.
217/**
218 * AST nodes cannot be copied or moved as all special member functions (aside from the destructor) are `delete`d. There
219 * will always be one instance for a specific node during the lifetype of the compiler.
220 * However note that AST nodes can be cloned with the `clone()` method, which will produce a deep copy. This is used
221 * when instantiating a template. The clone will have the exact same structure and locations but distinct types,
222 * depending on what the types the template is instantiated with.
223 */
224class AST {
225 /// Every subclass of `AST` has a distinct `Kind`.
226 const Kind m_kind;
227 /// The range of tokenizer `Token`s that this node was parsed from.
228 const span<Token> m_tok;
229 /// The value type of this node. Determined in the semantic phase; always empty after parsing.
230 optional<ty::Type> m_val_ty{};
231 /// \see Attachment
232 unique_ptr<Attachment> m_attach{std::make_unique<Attachment>()};
233
234protected:
235 /// Verify the type compatibility of the depends of this node, and merge the types if possible.
236 /// This is called every time the node's type is updated.
237 void unify_val_ty();
238
239 [[nodiscard]] auto tok() const noexcept -> span<Token> { return m_tok; }
240
241 AST(Kind kind, span<Token> tok) : m_kind(kind), m_tok(tok) {}
242
243public:
244 AST(const AST&) = delete;
245 AST(AST&&) = default;
246 auto operator=(const AST&) -> AST& = delete;
247 auto operator=(AST&&) -> AST& = delete;
248 virtual ~AST() = default;
249
250 /// Recursively visit this ast node and all its constituents. \see Visitor
251 virtual void visit(Visitor& visitor) const = 0;
252
253 [[nodiscard]] auto val_ty() const noexcept -> optional<ty::Type> { return m_val_ty; }
254 [[nodiscard]] auto ensure_ty() const -> ty::Type {
255 YUME_ASSERT(m_val_ty.has_value(), "Ensured that AST node has type, but one has not been assigned");
256 return *m_val_ty;
257 }
258 void val_ty(optional<ty::Type> type) {
259 m_val_ty = type;
260 for (auto* i : m_attach->observers)
261 i->unify_val_ty();
262 }
263
264 /// Make the type of this node depend on the type of `other`.
265 /// \sa Attachment
267 other->m_attach->observers.insert(this);
268 this->m_attach->depends.insert(other);
269 unify_val_ty();
270 }
271
272 [[nodiscard]] auto kind() const -> Kind { return m_kind; };
273 /// Human-readable string representation of the `Kind` of this node.
274 [[nodiscard]] auto kind_name() const -> string { return ast::kind_name(kind()); };
275 [[nodiscard]] auto token_range() const -> const span<Token>& { return m_tok; };
276
277 [[nodiscard]] auto equals_by_hash(ast::AST& other) const -> bool;
278
279 /// The union of the locations of the `Token`s making up this node.
280 [[nodiscard]] auto location() const -> Loc;
281
282 /// A short, string representation for debugging.
283 [[nodiscard]] virtual auto describe() const -> string;
284
285 /// Deep copy, except for the type and attachments.
286 [[nodiscard]] virtual auto clone() const -> AST* = 0;
287};
288
289/// Statements make up most things in source code.
290/**
291 * This includes declarations (such as function declarations) which must be at the top level of a program; or things
292 * such as if statements, which must be inside the bodies of functions, but have no associated value.
293 * Expressions (`Expr`) are subclasses of `Stmt`, but *do* have an associated value.
294 * Note that in a future version of the language, declarations could be moved to a separate class and the distinction
295 * between statements and expressions may be removed.
296 */
297class Stmt : public AST {
298protected:
299 using AST::AST;
300
301public:
302 static auto classof(const AST* a) -> bool { return a->kind() >= K_Stmt && a->kind() <= K_END_Stmt; }
303 [[nodiscard]] auto clone() const -> Stmt* override = 0;
304};
305
306/// \see AnyBase
308/// \see OptionalAnyBase
310
311/// A type **annotation**. This (`ast::Type`) is distinct from the actual type of a value (`ty::Type`).
312class Type : public AST {
313protected:
314 using AST::AST;
315
316public:
317 static auto classof(const AST* a) -> bool { return a->kind() >= K_Type && a->kind() <= K_END_Type; }
318 [[nodiscard]] auto clone() const -> Type* override = 0;
319};
320
321/// \see AnyBase
323
324/// \see OptionalAnyBase
326
327/// Just the name of a type, always capitalized.
328struct SimpleType final : public Type {
329public:
330 string name;
331
332 explicit SimpleType(span<Token> tok, string name) : Type(K_SimpleType, tok), name{move(name)} {}
333 void visit(Visitor& visitor) const override;
334 [[nodiscard]] auto describe() const -> string override { return name; }
335
336 static auto classof(const AST* a) -> bool { return a->kind() == K_SimpleType; }
337 [[nodiscard]] auto clone() const -> SimpleType* override;
338};
339
340/// A type with a `Qualifier` like `mut` or `[]` following.
341struct QualType final : public Type {
342public:
345
346 QualType(span<Token> tok, AnyType base, Qualifier qualifier)
347 : Type(K_QualType, tok), base{move(base)}, qualifier{qualifier} {}
348 void visit(Visitor& visitor) const override;
349 [[nodiscard]] auto describe() const -> string override;
350
351 static auto classof(const AST* a) -> bool { return a->kind() == K_QualType; }
352 [[nodiscard]] auto clone() const -> QualType* override;
353};
354
355/// The `self` type.
356struct SelfType final : public Type {
357public:
358 explicit SelfType(span<Token> tok) : Type(K_SelfType, tok) {}
359 void visit([[maybe_unused]] Visitor& visitor) const override {}
360 [[nodiscard]] auto describe() const -> string override { return "self"; }
361
362 static auto classof(const AST* a) -> bool { return a->kind() == K_SelfType; }
363 [[nodiscard]] auto clone() const -> SelfType* override;
364};
365
366/// A type which refers to a different type, specifically that of a struct field.
367struct ProxyType final : public Type {
368public:
369 string field;
370
371 explicit ProxyType(span<Token> tok, string field) : Type(K_ProxyType, tok), field{move(field)} {}
372 void visit(Visitor& visitor) const override;
373 [[nodiscard]] auto describe() const -> string override { return field; }
374
375 static auto classof(const AST* a) -> bool { return a->kind() == K_ProxyType; }
376 [[nodiscard]] auto clone() const -> ProxyType* override;
377};
378
379/// A function type \e i.e. `->(Foo,Bar)Baz`.
380struct FunctionType : public Type {
381public:
383 vector<AnyType> args;
384 bool fn_ptr;
385
386 FunctionType(span<Token> tok, OptionalType ret, vector<AnyType> args, bool fn_ptr)
387 : Type(K_FunctionType, tok), ret{move(ret)}, args{move(args)}, fn_ptr(fn_ptr) {}
388 void visit(Visitor& visitor) const override;
389 [[nodiscard]] auto describe() const -> string override;
390
391 static auto classof(const AST* a) -> bool { return a->kind() == K_FunctionType; }
392 [[nodiscard]] auto clone() const -> FunctionType* override;
393};
394
395/// A pair of a `Type` and an identifier, \e i.e. a parameter name.
396struct TypeName final : public AST {
398 string name;
399
400 TypeName(span<Token> tok, AnyType type, string name) : AST(K_TypeName, tok), type{move(type)}, name{move(name)} {}
401 void visit(Visitor& visitor) const override;
402 [[nodiscard]] auto describe() const -> string override { return name; }
403
404 static auto classof(const AST* a) -> bool { return a->kind() == K_TypeName; }
405 [[nodiscard]] auto clone() const -> TypeName* override;
406};
407
408/// A generic, compile-time argument to a struct or function definition, comparable to C++ template parameters.
409/// Like C++ templates, these can be non-type parameters. If it's a generic type parameter, such as the following:
410///
411/// \code{.ym}
412/// struct Array{T type}
413/// \endcode
414///
415/// The \p type field will be absent, and the \p name will be uppercased. Otherwise, it's a non-type generic parameter:
416///
417/// \code{.ym}
418/// struct StaticArray{n I32}
419/// \endcode
420///
421/// In this case, the \p type field be filled out with the specified type, and the \p name will be lowercase.
422struct GenericParam final : public AST {
424 string name;
425
426 GenericParam(span<Token> tok, OptionalType type, string name)
427 : AST(K_GenericParam, tok), type{move(type)}, name{move(name)} {}
428 void visit(Visitor& visitor) const override;
429 [[nodiscard]] auto describe() const -> string override { return name; }
430
431 [[nodiscard]] auto is_type_parameter() const -> bool { return !type.has_value(); }
432
433 static auto classof(const AST* a) -> bool { return a->kind() == K_GenericParam; }
434 [[nodiscard]] auto clone() const -> GenericParam* override;
435};
436
437/// Expressions have an associated value and type.
438class Expr : public Stmt {
439protected:
440 using Stmt::Stmt;
441
442public:
443 static auto classof(const AST* a) -> bool { return a->kind() >= K_Expr && a->kind() <= K_END_Expr; }
444 [[nodiscard]] auto clone() const -> Expr* override = 0;
445};
446
447/// \see AnyBase
449/// \see OptionalAnyBase
451
453 using visitable_variant::visitable_variant;
454
455 [[nodiscard]] auto ast() -> AST* {
456 return visit([](auto& v) -> AST* { return v.raw_ptr(); });
457 }
458 [[nodiscard]] auto ast() const -> const AST* {
459 return visit([](auto& v) -> const AST* { return v.raw_ptr(); });
460 }
461
462 [[nodiscard]] auto as_type() -> AnyType& { return std::get<AnyType>(*this); }
463 [[nodiscard]] auto as_expr() -> AnyExpr& { return std::get<AnyExpr>(*this); }
464};
465
466/// A type with explicit type parameters \e i.e. `Foo<Bar,Baz>`.
467struct TemplatedType final : public Type {
468public:
470 vector<AnyTypeOrExpr> type_args;
471
472 TemplatedType(span<Token> tok, AnyType base, vector<AnyTypeOrExpr> type_args)
473 : Type(K_TemplatedType, tok), base{move(base)}, type_args{move(type_args)} {}
474 void visit(Visitor& visitor) const override;
475 [[nodiscard]] auto describe() const -> string override;
476
477 static auto classof(const AST* a) -> bool { return a->kind() == K_TemplatedType; }
478 [[nodiscard]] auto clone() const -> TemplatedType* override;
479};
480
481/// Number literals.
482struct NumberExpr final : public Expr {
483public:
484 int64_t val;
485
486 explicit NumberExpr(span<Token> tok, int64_t val) : Expr(K_Number, tok), val(val) {}
487 void visit(Visitor& visitor) const override;
488 [[nodiscard]] auto describe() const -> string override { return std::to_string(val); }
489
490 static auto classof(const AST* a) -> bool { return a->kind() == K_Number; }
491 [[nodiscard]] auto clone() const -> NumberExpr* override;
492};
493
494/// Char literals.
495struct CharExpr final : public Expr {
496public:
497 uint8_t val;
498
499 explicit CharExpr(span<Token> tok, uint8_t val) : Expr(K_Char, tok), val(val) {}
500 void visit(Visitor& visitor) const override;
501 [[nodiscard]] auto describe() const -> string override { return std::to_string(val); }
502
503 static auto classof(const AST* a) -> bool { return a->kind() == K_Char; }
504 [[nodiscard]] auto clone() const -> CharExpr* override;
505};
506
507/// Bool literals (`true` or `false`).
508struct BoolExpr final : public Expr {
509public:
510 bool val;
511
512 explicit BoolExpr(span<Token> tok, bool val) : Expr(K_Bool, tok), val(val) {}
513 void visit(Visitor& visitor) const override;
514 [[nodiscard]] auto describe() const -> string override { return val ? "true" : "false"; }
515
516 static auto classof(const AST* a) -> bool { return a->kind() == K_Bool; }
517 [[nodiscard]] auto clone() const -> BoolExpr* override;
518};
519
520/// String literals.
521struct StringExpr final : public Expr {
522public:
523 string val;
524
525 explicit StringExpr(span<Token> tok, string val) : Expr(K_String, tok), val(move(val)) {}
526 void visit(Visitor& visitor) const override;
527 [[nodiscard]] auto describe() const -> string override { return val; }
528
529 static auto classof(const AST* a) -> bool { return a->kind() == K_String; }
530 [[nodiscard]] auto clone() const -> StringExpr* override;
531};
532
533/// A variable, \e i.e. just an identifier.
534struct VarExpr final : public Expr {
535public:
536 string name;
537
538 explicit VarExpr(span<Token> tok, string name) : Expr(K_Var, tok), name(move(name)) {}
539 void visit(Visitor& visitor) const override;
540 [[nodiscard]] auto describe() const -> string override { return name; }
541
542 static auto classof(const AST* a) -> bool { return a->kind() == K_Var; }
543 [[nodiscard]] auto clone() const -> VarExpr* override;
544};
545
546/// A constant. Currently global
547struct ConstExpr final : public Expr {
548public:
549 string name;
550 optional<string> parent;
551
552 ConstExpr(span<Token> tok, string name, optional<string> parent)
553 : Expr(K_Const, tok), name(move(name)), parent(move(parent)) {}
554 void visit(Visitor& visitor) const override;
555 [[nodiscard]] auto describe() const -> string override { return name; }
556
557 static auto classof(const AST* a) -> bool { return a->kind() == K_Const; }
558 [[nodiscard]] auto clone() const -> ConstExpr* override;
559};
560
561/// A function call or operator.
562struct CallExpr final : public Expr {
563public:
564 string name;
566 vector<AnyExpr> args;
567 /// During semantic analysis, the `TypeWalker` performs overload selection and saves the function declaration or
568 /// instantiation that this call refers to directly in the AST node, in this field.
569 Fn* selected_overload{};
570
571 CallExpr(span<Token> tok, string name, OptionalType receiver, vector<AnyExpr> args)
572 : Expr(K_Call, tok), name{move(name)}, receiver{move(receiver)}, args{move(args)} {}
573 void visit(Visitor& visitor) const override;
574 [[nodiscard]] auto describe() const -> string override { return name; }
575
576 static auto classof(const AST* a) -> bool { return a->kind() == K_Call; }
577 [[nodiscard]] auto clone() const -> CallExpr* override;
578};
579
580/// A logical operator such as `||` or `&&`. Since these aren't overloadable, they have their own AST node.
581struct BinaryLogicExpr final : public Expr {
582public:
586
587 BinaryLogicExpr(span<Token> tok, Atom operation, AnyExpr lhs, AnyExpr rhs)
588 : Expr(K_BinaryLogic, tok), operation{operation}, lhs{move(lhs)}, rhs{move(rhs)} {}
589 void visit(Visitor& visitor) const override;
590 [[nodiscard]] auto describe() const -> string override { return static_cast<string>(operation); }
591
592 static auto classof(const AST* a) -> bool { return a->kind() == K_BinaryLogic; }
593 [[nodiscard]] auto clone() const -> BinaryLogicExpr* override;
594};
595
596/// A construction of a struct or cast of a primitive.
597struct CtorExpr final : public Expr {
598public:
600 vector<AnyExpr> args;
601 /// During semantic analysis, the `TypeWalker` performs overload selection and saves the constructor declaration that
602 /// this call refers to directly in the AST node, in this field.
603 Fn* selected_overload{};
604
605 CtorExpr(span<Token> tok, AnyType type, vector<AnyExpr> args)
606 : Expr(K_Ctor, tok), type{move(type)}, args{move(args)} {}
607 void visit(Visitor& visitor) const override;
608 [[nodiscard]] auto describe() const -> string override { return type->describe(); }
609
610 static auto classof(const AST* a) -> bool { return a->kind() == K_Ctor; }
611 [[nodiscard]] auto clone() const -> CtorExpr* override;
612};
613
614/// A destruction of an object upon leaving its scope.
615/**
616 * This is currently marked deprecated as it is unused, however it is likely to be used again in the future, thus its
617 * logic remains here to avoid redeclaring it in the future.
618 */
619struct [[deprecated]] DtorExpr final : public Expr {
620public:
622
623 DtorExpr(span<Token> tok, AnyExpr base) : Expr(K_Dtor, tok), base{move(base)} {}
624 void visit(Visitor& visitor) const override;
625 [[nodiscard]] auto describe() const -> string override { return base->describe(); }
626
627 static auto classof(const AST* a) -> bool { return a->kind() == K_Dtor; }
628 [[nodiscard]] auto clone() const -> DtorExpr* override;
629};
630
631/// A slice literal, \e i.e. an array.
632struct SliceExpr final : public Expr {
633public:
635 vector<AnyExpr> args;
636
637 SliceExpr(span<Token> tok, AnyType type, vector<AnyExpr> args)
638 : Expr(K_Slice, tok), type{move(type)}, args{move(args)} {}
639 void visit(Visitor& visitor) const override;
640 [[nodiscard]] auto describe() const -> string override { return type->describe(); }
641
642 static auto classof(const AST* a) -> bool { return a->kind() == K_Slice; }
643 [[nodiscard]] auto clone() const -> SliceExpr* override;
644};
645
646/// An assignment (`=`).
647/**
648 * Assignment has a specific target (the left-hand side), and the value (the right-hand-side).
649 * The target may be multiple things, such as a variable `VarExpr` or field `FieldAccessExpr`.
650 * Note that some things such as indexed assignment `[]=` become a `CallExpr` instead.
651 */
652struct AssignExpr final : public Expr {
653public:
656
657 AssignExpr(span<Token> tok, AnyExpr target, AnyExpr value)
658 : Expr(K_Assign, tok), target{move(target)}, value{move(value)} {}
659 void visit(Visitor& visitor) const override;
660
661 static auto classof(const AST* a) -> bool { return a->kind() == K_Assign; }
662 [[nodiscard]] auto clone() const -> AssignExpr* override;
663};
664
665/// Direct access of a field of a struct (`::`).
666struct FieldAccessExpr final : public Expr {
667public:
669 string field;
670 int offset = -1;
671
672 FieldAccessExpr(span<Token> tok, OptionalExpr base, string field)
673 : Expr(K_FieldAccess, tok), base{move(base)}, field{move(field)} {}
674 void visit(Visitor& visitor) const override;
675
676 static auto classof(const AST* a) -> bool { return a->kind() == K_FieldAccess; }
677 [[nodiscard]] auto clone() const -> FieldAccessExpr* override;
678};
679
680/// Represents an implicit cast to a different type, performed during semantic analysis
681/**
682 * Note that implicit casts have no direct "textual" representation in actual source code, they are only materialized
683 * during semantic analysis.
684 */
685struct ImplicitCastExpr final : public Expr {
686public:
688 /// The conversion steps performed during this cast.
690
691 ImplicitCastExpr(span<Token> tok, AnyExpr base, ty::Conv conversion)
692 : Expr(K_ImplicitCast, tok), base{move(base)}, conversion{conversion} {}
693 void visit(Visitor& visitor) const override;
694
695 static auto classof(const AST* a) -> bool { return a->kind() == K_ImplicitCast; }
696 [[nodiscard]] auto clone() const -> ImplicitCastExpr* override;
697};
698
699/// Represents a reference to a type.
700struct TypeExpr final : public Expr {
701public:
703
704 TypeExpr(span<Token> tok, AnyType type) : Expr(K_TypeExpr, tok), type{move(type)} {}
705 void visit(Visitor& visitor) const override;
706
707 static auto classof(const AST* a) -> bool { return a->kind() == K_TypeExpr; }
708 [[nodiscard]] auto clone() const -> TypeExpr* override;
709};
710
711/// A statement consisting of multiple other statements, \e i.e. the body of a function.
712struct Compound final : public Stmt {
713public:
714 vector<AnyStmt> body;
715
716 void visit(Visitor& visitor) const override;
717 explicit Compound(span<Token> tok, vector<AnyStmt> body) : Stmt(K_Compound, tok), body{move(body)} {}
718
719 [[nodiscard]] auto begin() { return body.begin(); }
720 [[nodiscard]] auto end() { return body.end(); }
721 [[nodiscard]] auto begin() const { return body.begin(); }
722 [[nodiscard]] auto end() const { return body.end(); }
723
724 static auto classof(const AST* a) -> bool { return a->kind() == K_Compound; }
725 [[nodiscard]] auto clone() const -> Compound* override;
726};
727
728/// A local definition of an anonymous function
729struct LambdaExpr final : public Expr {
730public:
731 vector<TypeName> args;
734 std::set<string> annotations;
735 vector<string> closured_names{};
736 vector<AST*> closured_nodes{};
737 llvm::Function* llvm_fn{};
738
739 LambdaExpr(span<Token> tok, vector<TypeName> args, OptionalType ret, Compound body, std::set<string> annotations)
740 : Expr(K_Lambda, tok), args(move(args)), ret(move(ret)), body(move(body)), annotations(move(annotations)) {}
741 void visit(Visitor& visitor) const override;
742 // [[nodiscard]] auto describe() const -> string override; // TODO(rymiel)
743
744 static auto classof(const AST* a) -> bool { return a->kind() == K_Lambda; }
745 [[nodiscard]] auto clone() const -> LambdaExpr* override;
746};
747
748/// Base class for a named declaration.
749class Decl : public Stmt {
750protected:
751 using Stmt::Stmt;
752
753public:
754 static auto classof(const AST* a) -> bool { return a->kind() >= K_Decl && a->kind() <= K_END_Decl; }
755 [[nodiscard]] auto clone() const -> Decl* override = 0;
756
757 [[nodiscard]] virtual auto decl_name() const -> string = 0;
758 [[nodiscard]] auto describe() const -> string final { return decl_name(); }
759};
760
761/// A declaration of a function (`def`).
762struct FnDecl final : public Decl {
763public:
764 using extern_decl_t = struct {
765 string name;
767 };
768 using abstract_decl_t = struct {};
769
771 struct Body : public body_base_t {
772 using body_base_t::body_base_t;
773 };
774
775 static constexpr auto ANN_EXTERN = "extern";
776 static constexpr auto ANN_OVERRIDE = "override";
777
778 string name;
779 std::unordered_set<string> annotations;
780 vector<TypeName> args;
781 vector<GenericParam> type_args;
783 /// If this function declaration refers to a primitive, this field is a string representing the name of the primitive.
784 /// If it's an external method, this field is a pair of the extern name and whether the method is varargs.
785 /// Otherise, this function declaration refers to a regular function and this field holds the body of that function.
787 /// During semantic analysis, AST nodes are converted to a format better suited for semantic analysis. This field
788 /// will be set once said conversion is performed.
789 Fn* sema_decl{};
790
791 FnDecl(span<Token> tok, string name, vector<TypeName> args, vector<GenericParam> type_args, OptionalType ret,
792 Body body, std::unordered_set<string> annotations)
793 : Decl(K_FnDecl, tok), name{move(name)},
794 annotations(move(annotations)), args{move(args)}, type_args{move(type_args)}, ret{move(ret)}, body{move(body)} {
795 }
796 void visit(Visitor& visitor) const override;
797 [[nodiscard]] auto decl_name() const -> string override { return name; }
798
799 [[nodiscard]] auto varargs() const -> bool { return extern_decl() && std::get<extern_decl_t>(body).varargs; }
800 [[nodiscard]] auto primitive() const -> bool { return holds_alternative<string>(body); }
801 [[nodiscard]] auto extern_decl() const -> bool { return holds_alternative<extern_decl_t>(body); }
802 [[nodiscard]] auto abstract() const -> bool { return holds_alternative<abstract_decl_t>(body); }
803 [[nodiscard]] auto extern_linkage() const -> bool { return extern_decl() || annotations.contains(ANN_EXTERN); }
804 [[nodiscard]] auto override() const -> bool { return annotations.contains(ANN_OVERRIDE); }
805 void make_extern_linkage(bool value = true) {
806 if (value)
807 annotations.emplace(ANN_EXTERN);
808 else
809 annotations.erase(ANN_EXTERN);
810 }
811 static auto classof(const AST* a) -> bool { return a->kind() == K_FnDecl; }
812 [[nodiscard]] auto clone() const -> FnDecl* override;
813};
814
815/// A declaration of a custom constructor (`def :new`).
816/**
817 * The arguments of a constructor may be regular `TypeName`s, just as in regular function declarations, but they also
818 * may be a `FieldAccessExpr` without a base (such as `::x`), representing a shorthand where the field is set
819 * immediately, and the type is deduced to be that of the field.
820 * Essentially the following two declarations are identical:
821 * \code
822 * struct Foo(data I32)
823 * def :new(::data)
824 * end
825 *
826 * def :new(data I32)
827 * ::data = data
828 * end
829 * end
830 * \endcode
831 */
832struct CtorDecl final : public Decl {
833public:
834 vector<TypeName> args;
836
837 CtorDecl(span<Token> tok, vector<TypeName> args, Compound body)
838 : Decl(K_CtorDecl, tok), args{move(args)}, body{move(body)} {}
839 void visit(Visitor& visitor) const override;
840 [[nodiscard]] auto decl_name() const -> string override { return ":new"; } // TODO(rymiel): Magic value?
841
842 static auto classof(const AST* a) -> bool { return a->kind() == K_CtorDecl; }
843 [[nodiscard]] auto clone() const -> CtorDecl* override;
844};
845
846/// A declaration of a struct (`struct`) or an interface (`interface`).
847struct StructDecl final : public Decl {
848public:
849 string name;
850 vector<TypeName> fields;
851 vector<GenericParam> type_args;
854 std::unordered_set<string> annotations;
856
857 static constexpr auto BUILTIN_TYPE_SLICE = "__builtin_type_Slice";
858 static constexpr auto BUILTIN_TYPE_STATIC_ARRAY = "__builtin_type_StaticArray";
859
860 StructDecl(span<Token> tok, string name, vector<TypeName> fields, vector<GenericParam> type_args, Compound body,
861 OptionalType implements, std::unordered_set<string> annotations, bool is_interface = false)
862 : Decl(K_StructDecl, tok), name{move(name)}, fields{move(fields)}, type_args{move(type_args)}, body{move(body)},
863 implements{move(implements)}, annotations{move(annotations)}, is_interface{is_interface} {}
864 void visit(Visitor& visitor) const override;
865 [[nodiscard]] auto decl_name() const -> string override { return name; }
866
867 static auto classof(const AST* a) -> bool { return a->kind() == K_StructDecl; }
868 [[nodiscard]] auto clone() const -> StructDecl* override;
869};
870
871/// A declaration of a local variable (`let`).
872struct VarDecl final : public Decl {
873public:
874 string name;
877
878 VarDecl(span<Token> tok, string name, OptionalType type, AnyExpr init)
879 : Decl(K_VarDecl, tok), name{move(name)}, type{move(type)}, init(move(init)) {}
880 void visit(Visitor& visitor) const override;
881 [[nodiscard]] auto decl_name() const -> string override { return name; }
882
883 static auto classof(const AST* a) -> bool { return a->kind() == K_VarDecl; }
884 [[nodiscard]] auto clone() const -> VarDecl* override;
885};
886
887/// A declaration of a constant (`const`).
888struct ConstDecl final : public Decl {
889public:
890 string name;
891 AnyType type; // TODO(rymiel): make optional?
893
894 ConstDecl(span<Token> tok, string name, AnyType type, AnyExpr init)
895 : Decl(K_ConstDecl, tok), name{move(name)}, type{move(type)}, init(move(init)) {}
896 void visit(Visitor& visitor) const override;
897 [[nodiscard]] auto decl_name() const -> string override { return name; }
898
899 static auto classof(const AST* a) -> bool { return a->kind() == K_ConstDecl; }
900 [[nodiscard]] auto clone() const -> ConstDecl* override;
901};
902
903/// A while loop (`while`).
904struct WhileStmt final : public Stmt {
905public:
908
909 WhileStmt(span<Token> tok, AnyExpr cond, Compound body) : Stmt(K_While, tok), cond{move(cond)}, body{move(body)} {}
910 void visit(Visitor& visitor) const override;
911
912 static auto classof(const AST* a) -> bool { return a->kind() == K_While; }
913 [[nodiscard]] auto clone() const -> WhileStmt* override;
914};
915
916/// Clauses of an if statement `IfStmt`.
917struct IfClause final : public AST {
918public:
921
922 IfClause(span<Token> tok, AnyExpr cond, Compound body) : AST(K_IfClause, tok), cond{move(cond)}, body{move(body)} {}
923 void visit(Visitor& visitor) const override;
924
925 static auto classof(const AST* a) -> bool { return a->kind() == K_IfClause; }
926 [[nodiscard]] auto clone() const -> IfClause* override;
927};
928
929/// An if statement (`if`), with one or more `IfClause`s, and optionally an else clause.
930struct IfStmt final : public Stmt {
931public:
932 vector<IfClause> clauses;
933 optional<Compound> else_clause;
934
935 IfStmt(span<Token> tok, vector<IfClause> clauses, optional<Compound> else_clause)
936 : Stmt(K_If, tok), clauses{move(clauses)}, else_clause{move(else_clause)} {}
937 void visit(Visitor& visitor) const override;
938
939 static auto classof(const AST* a) -> bool { return a->kind() == K_If; }
940 [[nodiscard]] auto clone() const -> IfStmt* override;
941};
942
943/// Return from a function body.
944struct ReturnStmt final : public Stmt {
945public:
947 VarDecl* extends_lifetime{};
948
949 explicit ReturnStmt(span<Token> tok, OptionalExpr expr) : Stmt(K_Return, tok), expr{move(expr)} {}
950 void visit(Visitor& visitor) const override;
951
952 static auto classof(const AST* a) -> bool { return a->kind() == K_Return; }
953 [[nodiscard]] auto clone() const -> ReturnStmt* override;
954};
955
956/// The top level structure of a file of source code.
957struct Program final : public Stmt {
958public:
959 vector<AnyStmt> body;
960
961 explicit Program(span<Token> tok, vector<AnyStmt> body) : Stmt(K_Program, tok), body{move(body)} {}
962 void visit(Visitor& visitor) const override;
963 [[nodiscard]] static auto parse(TokenIterator& tokens, diagnostic::NotesHolder& notes) -> unique_ptr<Program>;
964
965 static auto classof(const AST* a) -> bool { return a->kind() == K_Program; }
966 [[nodiscard]] auto clone() const -> Program* override;
967};
968} // namespace yume::ast
969
970template <> struct std::hash<yume::ast::AST> {
971 auto operator()(const yume::ast::AST& s) const noexcept -> std::size_t;
972};
Atoms represent strings in a string pool.
Definition: atom.hpp:12
All nodes in the AST tree of the program inherit from this class.
Definition: ast.hpp:224
void attach_to(nonnull< AST * > other)
Make the type of this node depend on the type of other.
Definition: ast.hpp:266
auto operator=(const AST &) -> AST &=delete
auto operator=(AST &&) -> AST &=delete
auto val_ty() const noexcept -> optional< ty::Type >
Definition: ast.hpp:253
auto kind_name() const -> string
Human-readable string representation of the Kind of this node.
Definition: ast.hpp:274
AST(Kind kind, span< Token > tok)
Definition: ast.hpp:241
virtual auto clone() const -> AST *=0
Deep copy, except for the type and attachments.
auto kind() const -> Kind
Definition: ast.hpp:272
virtual auto describe() const -> string
A short, string representation for debugging.
Definition: describe.cpp:11
AST(AST &&)=default
auto token_range() const -> const span< Token > &
Definition: ast.hpp:275
void val_ty(optional< ty::Type > type)
Definition: ast.hpp:258
AST(const AST &)=delete
void unify_val_ty()
Verify the type compatibility of the depends of this node, and merge the types if possible....
Definition: ast.cpp:10
auto equals_by_hash(ast::AST &other) const -> bool
Definition: ast.cpp:37
auto location() const -> Loc
The union of the locations of the Tokens making up this node.
Definition: ast.cpp:28
auto ensure_ty() const -> ty::Type
Definition: ast.hpp:254
virtual void visit(Visitor &visitor) const =0
Recursively visit this ast node and all its constituents.
auto tok() const noexcept -> span< Token >
Definition: ast.hpp:239
virtual ~AST()=default
Represents "any" kind of ast node of type T. See AnyExpr, AnyStmt and AnyType.
Definition: ast.hpp:184
auto operator*() const -> const T &
Definition: ast.hpp:196
auto raw_ptr() -> T *
Definition: ast.hpp:201
auto operator->() -> T *
Definition: ast.hpp:197
auto operator->() const -> const T *
Definition: ast.hpp:195
AnyBase(T *raw_ptr)
Definition: ast.hpp:189
AnyBase(OptionalAnyBase< T > &&other)
Definition: ast.hpp:193
AnyBase(U uptr) noexcept
Definition: ast.hpp:190
auto operator*() -> T &
Definition: ast.hpp:198
auto raw_ptr() const -> const T *
Definition: ast.hpp:200
Base class for a named declaration.
Definition: ast.hpp:749
auto clone() const -> Decl *override=0
Deep copy, except for the type and attachments.
Expressions have an associated value and type.
Definition: ast.hpp:438
auto clone() const -> Expr *override=0
Deep copy, except for the type and attachments.
Represents "any" kind of ast node of type T, or the absence of one. See OptionalExpr and OptionalType...
Definition: ast.hpp:154
auto has_value() const -> bool
Definition: ast.hpp:172
auto operator*() -> T &
Definition: ast.hpp:169
auto raw_ptr() -> T *
Definition: ast.hpp:174
OptionalAnyBase(optional< unique_ptr< T > > opt_uptr)
Definition: ast.hpp:163
auto raw_ptr() const -> const T *
Definition: ast.hpp:173
OptionalAnyBase(std::nullopt_t)
Definition: ast.hpp:162
auto operator*() const -> const T &
Definition: ast.hpp:167
OptionalAnyBase(T *raw_ptr)
Definition: ast.hpp:160
auto operator->() const -> const T *
Definition: ast.hpp:166
auto operator->() -> T *
Definition: ast.hpp:168
Statements make up most things in source code.
Definition: ast.hpp:297
auto clone() const -> Stmt *override=0
Deep copy, except for the type and attachments.
An iterator-like holding Tokens, used when parsing.
Definition: parser.hpp:31
A type annotation. This (ast::Type) is distinct from the actual type of a value (ty::Type).
Definition: ast.hpp:312
auto clone() const -> Type *override=0
Deep copy, except for the type and attachments.
Definition: ast.hpp:20
Definition: ast.cpp:8
auto constexpr kind_name(Kind type) -> const char *
Definition: ast.hpp:90
@ K_Bool
BoolExpr
Definition: ast.hpp:62
@ K_String
StringExpr
Definition: ast.hpp:63
@ K_If
IfStmt
Definition: ast.hpp:45
@ K_BinaryLogic
BinaryLogicExpr
Definition: ast.hpp:67
@ K_Assign
AssignExpr
Definition: ast.hpp:72
@ K_ConstDecl
ConstDecl
Definition: ast.hpp:55
@ K_Dtor
DtorExpr
Definition: ast.hpp:69
@ K_END_Expr
Definition: ast.hpp:76
@ K_Number
NumberExpr
Definition: ast.hpp:60
@ K_ProxyType
ProxyType
Definition: ast.hpp:86
@ K_TemplatedType
TemplatedType
Definition: ast.hpp:83
@ K_Decl
Decl
Definition: ast.hpp:50
@ K_ImplicitCast
ImplicitCastExpr
Definition: ast.hpp:74
@ K_Expr
Expr
Definition: ast.hpp:59
@ K_Slice
SliceExpr
Definition: ast.hpp:70
@ K_QualType
QualType
Definition: ast.hpp:82
@ K_FieldAccess
FieldAccessExpr
Definition: ast.hpp:73
@ K_Type
Type
Definition: ast.hpp:80
@ K_Var
VarExpr
Definition: ast.hpp:64
@ K_END_Decl
Definition: ast.hpp:56
@ K_GenericParam
GenericParam
Definition: ast.hpp:39
@ K_Call
CallExpr
Definition: ast.hpp:66
@ K_Unknown
Unknown, default, zero value. Hopefully never encountered!
Definition: ast.hpp:36
@ K_TypeExpr
TypeExpr
Definition: ast.hpp:75
@ K_Compound
Compound
Definition: ast.hpp:43
@ K_FunctionType
TemplatedType
Definition: ast.hpp:84
@ K_Program
Program
Definition: ast.hpp:47
@ K_IfClause
IfClause
Definition: ast.hpp:37
@ K_VarDecl
VarDecl
Definition: ast.hpp:54
@ K_SelfType
SelfType
Definition: ast.hpp:85
@ K_Char
CharExpr
Definition: ast.hpp:61
@ K_Return
ReturnStmt
Definition: ast.hpp:46
@ K_SimpleType
SimpleType
Definition: ast.hpp:81
@ K_FnDecl
FnDecl
Definition: ast.hpp:51
@ K_CtorDecl
CtorDecl
Definition: ast.hpp:52
@ K_END_Stmt
Definition: ast.hpp:77
@ K_END_Type
Definition: ast.hpp:87
@ K_While
WhileStmt
Definition: ast.hpp:44
@ K_Const
ConstExpr
Definition: ast.hpp:65
@ K_Stmt
Stmt
Definition: ast.hpp:42
@ K_TypeName
TypeName
Definition: ast.hpp:38
@ K_StructDecl
StructDecl
Definition: ast.hpp:53
@ K_Lambda
LambdaExpr
Definition: ast.hpp:71
@ K_Ctor
CtorExpr
Definition: ast.hpp:68
Definition: ast.cpp:8
Qualifier
Definition: qualifier.hpp:4
T nonnull
Definition: util.hpp:73
A function declaration in the compiler.
Definition: vals.hpp:52
Represents a location in source code, as a range starting at a line and column and ending at some oth...
Definition: token.hpp:26
A categorized token in source code, created by the tokenizer. These tokens are consumed by the lexer.
Definition: token.hpp:80
auto as_type() -> AnyType &
Definition: ast.hpp:462
auto ast() -> AST *
Definition: ast.hpp:455
auto ast() const -> const AST *
Definition: ast.hpp:458
auto as_expr() -> AnyExpr &
Definition: ast.hpp:463
An assignment (=).
Definition: ast.hpp:652
AssignExpr(span< Token > tok, AnyExpr target, AnyExpr value)
Definition: ast.hpp:657
Represents the relationship between multiple AST nodes.
Definition: ast.hpp:209
llvm::SmallPtrSet< AST *, 2 > observers
Observers are the "children" and should have their type updated when this node's type changes.
Definition: ast.hpp:211
llvm::SmallPtrSet< AST *, 2 > depends
Depends are the "parents" and should be verified for type compatibility when this node's type changes...
Definition: ast.hpp:213
A logical operator such as || or &&. Since these aren't overloadable, they have their own AST node.
Definition: ast.hpp:581
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:590
BinaryLogicExpr(span< Token > tok, Atom operation, AnyExpr lhs, AnyExpr rhs)
Definition: ast.hpp:587
Bool literals (true or false).
Definition: ast.hpp:508
BoolExpr(span< Token > tok, bool val)
Definition: ast.hpp:512
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:514
A function call or operator.
Definition: ast.hpp:562
CallExpr(span< Token > tok, string name, OptionalType receiver, vector< AnyExpr > args)
Definition: ast.hpp:571
OptionalType receiver
Definition: ast.hpp:565
vector< AnyExpr > args
Definition: ast.hpp:566
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:574
Char literals.
Definition: ast.hpp:495
CharExpr(span< Token > tok, uint8_t val)
Definition: ast.hpp:499
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:501
A statement consisting of multiple other statements, i.e. the body of a function.
Definition: ast.hpp:712
auto begin() const
Definition: ast.hpp:721
Compound(span< Token > tok, vector< AnyStmt > body)
Definition: ast.hpp:717
auto end() const
Definition: ast.hpp:722
vector< AnyStmt > body
Definition: ast.hpp:714
A declaration of a constant (const).
Definition: ast.hpp:888
ConstDecl(span< Token > tok, string name, AnyType type, AnyExpr init)
Definition: ast.hpp:894
auto decl_name() const -> string override
Definition: ast.hpp:897
A constant. Currently global.
Definition: ast.hpp:547
optional< string > parent
Definition: ast.hpp:550
ConstExpr(span< Token > tok, string name, optional< string > parent)
Definition: ast.hpp:552
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:555
A declaration of a custom constructor (def :new).
Definition: ast.hpp:832
auto decl_name() const -> string override
Definition: ast.hpp:840
Compound body
Definition: ast.hpp:835
vector< TypeName > args
Definition: ast.hpp:834
CtorDecl(span< Token > tok, vector< TypeName > args, Compound body)
Definition: ast.hpp:837
A construction of a struct or cast of a primitive.
Definition: ast.hpp:597
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:608
vector< AnyExpr > args
Definition: ast.hpp:600
AnyType type
Definition: ast.hpp:599
CtorExpr(span< Token > tok, AnyType type, vector< AnyExpr > args)
Definition: ast.hpp:605
A destruction of an object upon leaving its scope.
Definition: ast.hpp:619
AnyExpr base
Definition: ast.hpp:621
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:625
DtorExpr(span< Token > tok, AnyExpr base)
Definition: ast.hpp:623
Direct access of a field of a struct (::).
Definition: ast.hpp:666
FieldAccessExpr(span< Token > tok, OptionalExpr base, string field)
Definition: ast.hpp:672
OptionalExpr base
Definition: ast.hpp:668
A declaration of a function (def).
Definition: ast.hpp:762
auto decl_name() const -> string override
Definition: ast.hpp:797
auto extern_linkage() const -> bool
Definition: ast.hpp:803
Body body
If this function declaration refers to a primitive, this field is a string representing the name of t...
Definition: ast.hpp:786
void make_extern_linkage(bool value=true)
Definition: ast.hpp:805
{ string name extern_decl_t
Definition: ast.hpp:765
vector< TypeName > args
Definition: ast.hpp:780
FnDecl(span< Token > tok, string name, vector< TypeName > args, vector< GenericParam > type_args, OptionalType ret, Body body, std::unordered_set< string > annotations)
Definition: ast.hpp:791
std::unordered_set< string > annotations
Definition: ast.hpp:779
{} abstract_decl_t
Definition: ast.hpp:768
auto extern_decl() const -> bool
Definition: ast.hpp:801
vector< GenericParam > type_args
Definition: ast.hpp:781
auto varargs() const -> bool
Definition: ast.hpp:799
string name
Definition: ast.hpp:778
OptionalType ret
Definition: ast.hpp:782
auto primitive() const -> bool
Definition: ast.hpp:800
auto abstract() const -> bool
Definition: ast.hpp:802
A function type i.e. ->(Foo,Bar)Baz.
Definition: ast.hpp:380
OptionalType ret
Definition: ast.hpp:382
vector< AnyType > args
Definition: ast.hpp:383
FunctionType(span< Token > tok, OptionalType ret, vector< AnyType > args, bool fn_ptr)
Definition: ast.hpp:386
A generic, compile-time argument to a struct or function definition, comparable to C++ template param...
Definition: ast.hpp:422
OptionalType type
Definition: ast.hpp:423
auto is_type_parameter() const -> bool
Definition: ast.hpp:431
GenericParam(span< Token > tok, OptionalType type, string name)
Definition: ast.hpp:426
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:429
Clauses of an if statement IfStmt.
Definition: ast.hpp:917
Compound body
Definition: ast.hpp:920
IfClause(span< Token > tok, AnyExpr cond, Compound body)
Definition: ast.hpp:922
AnyExpr cond
Definition: ast.hpp:919
An if statement (if), with one or more IfClauses, and optionally an else clause.
Definition: ast.hpp:930
optional< Compound > else_clause
Definition: ast.hpp:933
vector< IfClause > clauses
Definition: ast.hpp:932
IfStmt(span< Token > tok, vector< IfClause > clauses, optional< Compound > else_clause)
Definition: ast.hpp:935
Represents an implicit cast to a different type, performed during semantic analysis.
Definition: ast.hpp:685
ty::Conv conversion
The conversion steps performed during this cast.
Definition: ast.hpp:689
ImplicitCastExpr(span< Token > tok, AnyExpr base, ty::Conv conversion)
Definition: ast.hpp:691
A local definition of an anonymous function.
Definition: ast.hpp:729
OptionalType ret
Definition: ast.hpp:732
vector< TypeName > args
Definition: ast.hpp:731
LambdaExpr(span< Token > tok, vector< TypeName > args, OptionalType ret, Compound body, std::set< string > annotations)
Definition: ast.hpp:739
std::set< string > annotations
Definition: ast.hpp:734
Number literals.
Definition: ast.hpp:482
NumberExpr(span< Token > tok, int64_t val)
Definition: ast.hpp:486
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:488
The top level structure of a file of source code.
Definition: ast.hpp:957
Program(span< Token > tok, vector< AnyStmt > body)
Definition: ast.hpp:961
vector< AnyStmt > body
Definition: ast.hpp:959
A type which refers to a different type, specifically that of a struct field.
Definition: ast.hpp:367
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:373
ProxyType(span< Token > tok, string field)
Definition: ast.hpp:371
A type with a Qualifier like mut or [] following.
Definition: ast.hpp:341
AnyType base
Definition: ast.hpp:343
QualType(span< Token > tok, AnyType base, Qualifier qualifier)
Definition: ast.hpp:346
Qualifier qualifier
Definition: ast.hpp:344
Return from a function body.
Definition: ast.hpp:944
OptionalExpr expr
Definition: ast.hpp:946
ReturnStmt(span< Token > tok, OptionalExpr expr)
Definition: ast.hpp:949
The self type.
Definition: ast.hpp:356
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:360
void visit(Visitor &visitor) const override
Recursively visit this ast node and all its constituents.
Definition: ast.hpp:359
SelfType(span< Token > tok)
Definition: ast.hpp:358
Just the name of a type, always capitalized.
Definition: ast.hpp:328
SimpleType(span< Token > tok, string name)
Definition: ast.hpp:332
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:334
A slice literal, i.e. an array.
Definition: ast.hpp:632
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:640
SliceExpr(span< Token > tok, AnyType type, vector< AnyExpr > args)
Definition: ast.hpp:637
vector< AnyExpr > args
Definition: ast.hpp:635
String literals.
Definition: ast.hpp:521
StringExpr(span< Token > tok, string val)
Definition: ast.hpp:525
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:527
A declaration of a struct (struct) or an interface (interface).
Definition: ast.hpp:847
vector< GenericParam > type_args
Definition: ast.hpp:851
std::unordered_set< string > annotations
Definition: ast.hpp:854
StructDecl(span< Token > tok, string name, vector< TypeName > fields, vector< GenericParam > type_args, Compound body, OptionalType implements, std::unordered_set< string > annotations, bool is_interface=false)
Definition: ast.hpp:860
OptionalType implements
Definition: ast.hpp:853
vector< TypeName > fields
Definition: ast.hpp:850
auto decl_name() const -> string override
Definition: ast.hpp:865
A type with explicit type parameters i.e. Foo<Bar,Baz>.
Definition: ast.hpp:467
TemplatedType(span< Token > tok, AnyType base, vector< AnyTypeOrExpr > type_args)
Definition: ast.hpp:472
vector< AnyTypeOrExpr > type_args
Definition: ast.hpp:470
Represents a reference to a type.
Definition: ast.hpp:700
AnyType type
Definition: ast.hpp:702
TypeExpr(span< Token > tok, AnyType type)
Definition: ast.hpp:704
A pair of a Type and an identifier, i.e. a parameter name.
Definition: ast.hpp:396
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:402
AnyType type
Definition: ast.hpp:397
TypeName(span< Token > tok, AnyType type, string name)
Definition: ast.hpp:400
A declaration of a local variable (let).
Definition: ast.hpp:872
VarDecl(span< Token > tok, string name, OptionalType type, AnyExpr init)
Definition: ast.hpp:878
AnyExpr init
Definition: ast.hpp:876
auto decl_name() const -> string override
Definition: ast.hpp:881
OptionalType type
Definition: ast.hpp:875
A variable, i.e. just an identifier.
Definition: ast.hpp:534
auto describe() const -> string override
A short, string representation for debugging.
Definition: ast.hpp:540
VarExpr(span< Token > tok, string name)
Definition: ast.hpp:538
A while loop (while).
Definition: ast.hpp:904
WhileStmt(span< Token > tok, AnyExpr cond, Compound body)
Definition: ast.hpp:909
Compound body
Definition: ast.hpp:907
#define YUME_ASSERT(assertion, message)
Definition: util.hpp:81
Visitor & visitor
Definition: visit.cpp:17