9#include <llvm/ADT/SmallPtrSet.h>
10#include <llvm/Support/ErrorHandling.h>
15#include <unordered_set>
95 case K_Char:
return "char";
96 case K_Bool:
return "bool";
112 case K_While:
return "while-statement";
113 case K_If:
return "if-statement";
115 case K_Call:
return "call";
117 case K_Ctor:
return "constructor";
118 case K_Dtor:
return "destructor";
120 case K_Var:
return "var";
123 case K_Return:
return "return-statement";
136 case K_END_Type: llvm_unreachable(
"Invalid type name for ast node");
142template <
typename T>
class AnyBase;
161 template <std::convertible_to<unique_ptr<T>> U>
OptionalAnyBase(U uptr) : m_val{move(uptr)} {}
164 : m_val{opt_uptr.
has_value() ? move(*opt_uptr) : nullptr} {}
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->(); }
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(); }
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");
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; }
200 [[nodiscard]]
auto raw_ptr() const -> const T* {
return Super::m_val.get(); }
201 [[nodiscard]]
auto raw_ptr() -> T* {
return Super::m_val.get(); }
228 const span<Token> m_tok;
230 optional<ty::Type> m_val_ty{};
232 unique_ptr<Attachment> m_attach{std::make_unique<Attachment>()};
239 [[nodiscard]]
auto tok() const noexcept -> span<
Token> {
return m_tok; }
253 [[nodiscard]]
auto val_ty() const noexcept -> optional<ty::
Type> {
return m_val_ty; }
255 YUME_ASSERT(m_val_ty.has_value(),
"Ensured that AST node has type, but one has not been assigned");
260 for (
auto* i : m_attach->observers)
267 other->m_attach->observers.insert(
this);
268 this->m_attach->depends.insert(other);
272 [[nodiscard]]
auto kind() const ->
Kind {
return m_kind; };
283 [[nodiscard]] virtual auto
describe() const ->
string;
286 [[nodiscard]] virtual auto
clone() const ->
AST* = 0;
334 [[nodiscard]]
auto describe() const ->
string override {
return name; }
337 [[nodiscard]]
auto clone() const -> SimpleType* override;
349 [[nodiscard]]
auto describe() const ->
string override;
352 [[nodiscard]]
auto clone() const -> QualType* override;
360 [[nodiscard]]
auto describe() const ->
string override {
return "self"; }
363 [[nodiscard]]
auto clone() const -> SelfType* override;
373 [[nodiscard]]
auto describe() const ->
string override {
return field; }
376 [[nodiscard]]
auto clone() const -> ProxyType* override;
389 [[nodiscard]]
auto describe() const ->
string override;
392 [[nodiscard]]
auto clone() const -> FunctionType* override;
402 [[nodiscard]]
auto describe() const ->
string override {
return name; }
405 [[nodiscard]]
auto clone() const -> TypeName* override;
429 [[nodiscard]]
auto describe() const ->
string override {
return name; }
434 [[nodiscard]]
auto clone() const -> GenericParam* override;
453 using visitable_variant::visitable_variant;
456 return visit([](
auto& v) ->
AST* {
return v.raw_ptr(); });
458 [[nodiscard]]
auto ast() const -> const
AST* {
459 return visit([](
auto& v) ->
const AST* {
return v.raw_ptr(); });
475 [[nodiscard]]
auto describe() const ->
string override;
478 [[nodiscard]]
auto clone() const -> TemplatedType* override;
488 [[nodiscard]]
auto describe() const ->
string override {
return std::to_string(val); }
490 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_Number; }
491 [[nodiscard]]
auto clone() const -> NumberExpr* override;
501 [[nodiscard]]
auto describe() const ->
string override {
return std::to_string(val); }
503 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_Char; }
504 [[nodiscard]]
auto clone() const -> CharExpr* override;
514 [[nodiscard]]
auto describe() const ->
string override {
return val ?
"true" :
"false"; }
516 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_Bool; }
517 [[nodiscard]]
auto clone() const -> BoolExpr* override;
527 [[nodiscard]]
auto describe() const ->
string override {
return val; }
529 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_String; }
530 [[nodiscard]]
auto clone() const -> StringExpr* override;
540 [[nodiscard]]
auto describe() const ->
string override {
return name; }
542 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_Var; }
543 [[nodiscard]]
auto clone() const -> VarExpr* override;
555 [[nodiscard]]
auto describe() const ->
string override {
return name; }
557 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_Const; }
558 [[nodiscard]]
auto clone() const -> ConstExpr* override;
569 Fn* selected_overload{};
572 :
Expr(
K_Call,
tok), name{move(name)}, receiver{move(receiver)}, args{move(args)} {}
574 [[nodiscard]]
auto describe() const ->
string override {
return name; }
576 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_Call; }
577 [[nodiscard]]
auto clone() const -> CallExpr* override;
590 [[nodiscard]]
auto describe() const ->
string override {
return static_cast<string>(operation); }
593 [[nodiscard]]
auto clone() const -> BinaryLogicExpr* override;
603 Fn* selected_overload{};
608 [[nodiscard]]
auto describe() const ->
string override {
return type->describe(); }
610 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_Ctor; }
611 [[nodiscard]]
auto clone() const -> CtorExpr* override;
625 [[nodiscard]]
auto describe() const ->
string override {
return base->describe(); }
627 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_Dtor; }
628 [[nodiscard]]
auto clone() const -> DtorExpr* override;
640 [[nodiscard]]
auto describe() const ->
string override {
return type->describe(); }
642 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_Slice; }
643 [[nodiscard]]
auto clone() const -> SliceExpr* override;
661 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_Assign; }
662 [[nodiscard]]
auto clone() const -> AssignExpr* override;
677 [[nodiscard]]
auto clone() const -> FieldAccessExpr* override;
696 [[nodiscard]]
auto clone() const -> ImplicitCastExpr* override;
708 [[nodiscard]]
auto clone() const -> TypeExpr* override;
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(); }
725 [[nodiscard]]
auto clone() const -> Compound* override;
735 vector<string> closured_names{};
736 vector<AST*> closured_nodes{};
737 llvm::Function* llvm_fn{};
740 :
Expr(
K_Lambda,
tok), args(move(args)), ret(move(ret)), body(move(body)), annotations(move(annotations)) {}
744 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_Lambda; }
745 [[nodiscard]]
auto clone() const -> LambdaExpr* override;
757 [[nodiscard]] virtual auto decl_name() const ->
string = 0;
758 [[nodiscard]] auto
describe() const ->
string final {
return decl_name(); }
772 using body_base_t::body_base_t;
775 static constexpr auto ANN_EXTERN =
"extern";
776 static constexpr auto ANN_OVERRIDE =
"override";
792 Body body, std::unordered_set<string> annotations)
794 annotations(move(annotations)), args{move(args)}, type_args{move(type_args)}, ret{move(ret)}, body{move(body)} {
797 [[nodiscard]]
auto decl_name() const ->
string override {
return name; }
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); }
807 annotations.emplace(ANN_EXTERN);
809 annotations.erase(ANN_EXTERN);
811 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_FnDecl; }
812 [[nodiscard]]
auto clone() const -> FnDecl* override;
840 [[nodiscard]]
auto decl_name() const ->
string override {
return ":new"; }
843 [[nodiscard]]
auto clone() const -> CtorDecl* override;
857 static constexpr auto BUILTIN_TYPE_SLICE =
"__builtin_type_Slice";
858 static constexpr auto BUILTIN_TYPE_STATIC_ARRAY =
"__builtin_type_StaticArray";
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} {}
865 [[nodiscard]]
auto decl_name() const ->
string override {
return name; }
868 [[nodiscard]]
auto clone() const -> StructDecl* override;
879 :
Decl(
K_VarDecl,
tok), name{move(name)}, type{move(type)}, init(move(init)) {}
881 [[nodiscard]]
auto decl_name() const ->
string override {
return name; }
883 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_VarDecl; }
884 [[nodiscard]]
auto clone() const -> VarDecl* override;
897 [[nodiscard]]
auto decl_name() const ->
string override {
return name; }
900 [[nodiscard]]
auto clone() const -> ConstDecl* override;
912 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_While; }
913 [[nodiscard]]
auto clone() const -> WhileStmt* override;
926 [[nodiscard]]
auto clone() const -> IfClause* override;
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)} {}
939 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_If; }
940 [[nodiscard]]
auto clone() const -> IfStmt* override;
952 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_Return; }
953 [[nodiscard]]
auto clone() const -> ReturnStmt* override;
965 static auto classof(
const AST* a) ->
bool {
return a->
kind() ==
K_Program; }
966 [[nodiscard]]
auto clone() const -> Program* override;
970template <> struct std::hash<
yume::ast::
AST> {
971 auto operator()(
const yume::ast::AST& s)
const noexcept -> std::size_t;
Atoms represent strings in a string pool.
All nodes in the AST tree of the program inherit from this class.
void attach_to(nonnull< AST * > other)
Make the type of this node depend on the type of other.
auto operator=(const AST &) -> AST &=delete
auto operator=(AST &&) -> AST &=delete
auto val_ty() const noexcept -> optional< ty::Type >
auto kind_name() const -> string
Human-readable string representation of the Kind of this node.
AST(Kind kind, span< Token > tok)
virtual auto clone() const -> AST *=0
Deep copy, except for the type and attachments.
auto kind() const -> Kind
virtual auto describe() const -> string
A short, string representation for debugging.
auto token_range() const -> const span< Token > &
void val_ty(optional< ty::Type > type)
void unify_val_ty()
Verify the type compatibility of the depends of this node, and merge the types if possible....
auto equals_by_hash(ast::AST &other) const -> bool
auto location() const -> Loc
The union of the locations of the Tokens making up this node.
auto ensure_ty() const -> ty::Type
virtual void visit(Visitor &visitor) const =0
Recursively visit this ast node and all its constituents.
auto tok() const noexcept -> span< Token >
Represents "any" kind of ast node of type T. See AnyExpr, AnyStmt and AnyType.
auto operator*() const -> const T &
auto operator->() const -> const T *
AnyBase(OptionalAnyBase< T > &&other)
auto raw_ptr() const -> const T *
Base class for a named declaration.
auto clone() const -> Decl *override=0
Deep copy, except for the type and attachments.
Expressions have an associated value and type.
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...
auto has_value() const -> bool
OptionalAnyBase(optional< unique_ptr< T > > opt_uptr)
auto raw_ptr() const -> const T *
OptionalAnyBase(std::nullopt_t)
auto operator*() const -> const T &
OptionalAnyBase(T *raw_ptr)
auto operator->() const -> const T *
Statements make up most things in source code.
auto clone() const -> Stmt *override=0
Deep copy, except for the type and attachments.
An iterator-like holding Tokens, used when parsing.
A type annotation. This (ast::Type) is distinct from the actual type of a value (ty::Type).
auto clone() const -> Type *override=0
Deep copy, except for the type and attachments.
auto constexpr kind_name(Kind type) -> const char *
@ K_BinaryLogic
BinaryLogicExpr
@ K_TemplatedType
TemplatedType
@ K_ImplicitCast
ImplicitCastExpr
@ K_FieldAccess
FieldAccessExpr
@ K_GenericParam
GenericParam
@ K_Unknown
Unknown, default, zero value. Hopefully never encountered!
@ K_FunctionType
TemplatedType
A function declaration in the compiler.
Represents a location in source code, as a range starting at a line and column and ending at some oth...
A categorized token in source code, created by the tokenizer. These tokens are consumed by the lexer.
auto as_type() -> AnyType &
auto ast() const -> const AST *
auto as_expr() -> AnyExpr &
AssignExpr(span< Token > tok, AnyExpr target, AnyExpr value)
Represents the relationship between multiple AST nodes.
llvm::SmallPtrSet< AST *, 2 > observers
Observers are the "children" and should have their type updated when this node's type changes.
llvm::SmallPtrSet< AST *, 2 > depends
Depends are the "parents" and should be verified for type compatibility when this node's type changes...
A logical operator such as || or &&. Since these aren't overloadable, they have their own AST node.
auto describe() const -> string override
A short, string representation for debugging.
BinaryLogicExpr(span< Token > tok, Atom operation, AnyExpr lhs, AnyExpr rhs)
Bool literals (true or false).
BoolExpr(span< Token > tok, bool val)
auto describe() const -> string override
A short, string representation for debugging.
A function call or operator.
CallExpr(span< Token > tok, string name, OptionalType receiver, vector< AnyExpr > args)
auto describe() const -> string override
A short, string representation for debugging.
CharExpr(span< Token > tok, uint8_t val)
auto describe() const -> string override
A short, string representation for debugging.
A statement consisting of multiple other statements, i.e. the body of a function.
Compound(span< Token > tok, vector< AnyStmt > body)
A declaration of a constant (const).
ConstDecl(span< Token > tok, string name, AnyType type, AnyExpr init)
auto decl_name() const -> string override
A constant. Currently global.
optional< string > parent
ConstExpr(span< Token > tok, string name, optional< string > parent)
auto describe() const -> string override
A short, string representation for debugging.
A declaration of a custom constructor (def :new).
auto decl_name() const -> string override
CtorDecl(span< Token > tok, vector< TypeName > args, Compound body)
A construction of a struct or cast of a primitive.
auto describe() const -> string override
A short, string representation for debugging.
CtorExpr(span< Token > tok, AnyType type, vector< AnyExpr > args)
A destruction of an object upon leaving its scope.
auto describe() const -> string override
A short, string representation for debugging.
DtorExpr(span< Token > tok, AnyExpr base)
Direct access of a field of a struct (::).
FieldAccessExpr(span< Token > tok, OptionalExpr base, string field)
A declaration of a function (def).
auto decl_name() const -> string override
auto extern_linkage() const -> bool
Body body
If this function declaration refers to a primitive, this field is a string representing the name of t...
void make_extern_linkage(bool value=true)
{ string name extern_decl_t
FnDecl(span< Token > tok, string name, vector< TypeName > args, vector< GenericParam > type_args, OptionalType ret, Body body, std::unordered_set< string > annotations)
std::unordered_set< string > annotations
auto extern_decl() const -> bool
vector< GenericParam > type_args
auto varargs() const -> bool
auto primitive() const -> bool
auto abstract() const -> bool
A function type i.e. ->(Foo,Bar)Baz.
FunctionType(span< Token > tok, OptionalType ret, vector< AnyType > args, bool fn_ptr)
A generic, compile-time argument to a struct or function definition, comparable to C++ template param...
auto is_type_parameter() const -> bool
GenericParam(span< Token > tok, OptionalType type, string name)
auto describe() const -> string override
A short, string representation for debugging.
Clauses of an if statement IfStmt.
IfClause(span< Token > tok, AnyExpr cond, Compound body)
An if statement (if), with one or more IfClauses, and optionally an else clause.
optional< Compound > else_clause
vector< IfClause > clauses
IfStmt(span< Token > tok, vector< IfClause > clauses, optional< Compound > else_clause)
Represents an implicit cast to a different type, performed during semantic analysis.
ty::Conv conversion
The conversion steps performed during this cast.
ImplicitCastExpr(span< Token > tok, AnyExpr base, ty::Conv conversion)
A local definition of an anonymous function.
LambdaExpr(span< Token > tok, vector< TypeName > args, OptionalType ret, Compound body, std::set< string > annotations)
std::set< string > annotations
NumberExpr(span< Token > tok, int64_t val)
auto describe() const -> string override
A short, string representation for debugging.
The top level structure of a file of source code.
Program(span< Token > tok, vector< AnyStmt > body)
A type which refers to a different type, specifically that of a struct field.
auto describe() const -> string override
A short, string representation for debugging.
ProxyType(span< Token > tok, string field)
A type with a Qualifier like mut or [] following.
QualType(span< Token > tok, AnyType base, Qualifier qualifier)
Return from a function body.
ReturnStmt(span< Token > tok, OptionalExpr expr)
auto describe() const -> string override
A short, string representation for debugging.
void visit(Visitor &visitor) const override
Recursively visit this ast node and all its constituents.
SelfType(span< Token > tok)
Just the name of a type, always capitalized.
SimpleType(span< Token > tok, string name)
auto describe() const -> string override
A short, string representation for debugging.
A slice literal, i.e. an array.
auto describe() const -> string override
A short, string representation for debugging.
SliceExpr(span< Token > tok, AnyType type, vector< AnyExpr > args)
StringExpr(span< Token > tok, string val)
auto describe() const -> string override
A short, string representation for debugging.
A declaration of a struct (struct) or an interface (interface).
vector< GenericParam > type_args
std::unordered_set< string > annotations
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)
vector< TypeName > fields
auto decl_name() const -> string override
A type with explicit type parameters i.e. Foo<Bar,Baz>.
TemplatedType(span< Token > tok, AnyType base, vector< AnyTypeOrExpr > type_args)
vector< AnyTypeOrExpr > type_args
Represents a reference to a type.
TypeExpr(span< Token > tok, AnyType type)
A pair of a Type and an identifier, i.e. a parameter name.
auto describe() const -> string override
A short, string representation for debugging.
TypeName(span< Token > tok, AnyType type, string name)
A declaration of a local variable (let).
VarDecl(span< Token > tok, string name, OptionalType type, AnyExpr init)
auto decl_name() const -> string override
A variable, i.e. just an identifier.
auto describe() const -> string override
A short, string representation for debugging.
VarExpr(span< Token > tok, string name)
WhileStmt(span< Token > tok, AnyExpr cond, Compound body)
#define YUME_ASSERT(assertion, message)