Yume
vals.cpp
Go to the documentation of this file.
1#include "vals.hpp"
2#include "ast/ast.hpp"
3#include "ty/substitution.hpp"
4#include <algorithm>
5#include <stdexcept>
6#include <type_traits>
7
8namespace yume {
9static constexpr const auto always_false = [](auto&&... /* ignored */) { return false; };
10
11template <StringLiteral msg, typename RetT = void>
12static constexpr const auto always_throw =
13 [](auto&&... /* ignored */) -> RetT { throw std::runtime_error{static_cast<const char*>(msg.value)}; };
14
15template <auto pm, typename R = void>
16static constexpr const auto fwd = [](auto&&... args) -> R { return std::invoke(pm, args...); };
17template <auto pm>
18static constexpr const auto fwd<pm, void> = [](auto&&... args) -> decltype(auto) { return std::invoke(pm, args...); };
19
20auto Fn::create_instantiation(Substitutions& subs) noexcept -> Fn& {
21 auto def_clone = def.visit([this](auto* ast) -> Def {
22 auto* cloned = ast->clone();
23 member->body.emplace_back(cloned);
24 return cloned;
25 });
26
27 auto self_ty_clone = self_ty;
28 if (self_ty.has_value())
29 self_ty_clone = self_ty->apply_generic_substitution(subs);
30
31 auto fn_ptr = std::make_unique<Fn>(def_clone, member, self_ty_clone, subs);
32 auto new_emplace = instantiations.emplace(subs, move(fn_ptr));
33 return *new_emplace.first->second;
34}
35
36auto Fn::get_or_create_instantiation(Substitutions& subs) noexcept -> std::pair<bool, Fn&> {
37 auto existing_instantiation = instantiations.find(subs);
38 if (existing_instantiation == instantiations.end())
39 return {false, create_instantiation(subs)};
40
41 return {true, *existing_instantiation->second};
42}
43
45 auto* decl_clone = st_ast.clone();
46 member->body.emplace_back(decl_clone);
47
48 // errs() << " !!! Instantiating new " << name() << " with ";
49 // subs.dump(errs());
50 // errs() << "\n";
51 auto st_ptr = std::make_unique<Struct>(*decl_clone, member, self_ty, subs);
52 auto new_emplace = instantiations.emplace(subs, move(st_ptr));
53 return *new_emplace.first->second;
54}
55
56auto Struct::get_or_create_instantiation(Substitutions& subs) noexcept -> std::pair<bool, Struct&> {
57 auto existing_instantiation = instantiations.find(subs);
58 if (existing_instantiation == instantiations.end())
59 return {false, create_instantiation(subs)};
60
61 return {true, *existing_instantiation->second};
62}
63
64auto Fn::name() const noexcept -> string {
65 return def.visit([](ast::LambdaExpr* /*lambda*/) { return "<lambda>"s; }, // TODO(rymiel): Magic value?
66 [](auto* ast) { return ast->decl_name(); });
67}
68auto Struct::name() const noexcept -> string { return st_ast.name; }
69auto Const::name() const noexcept -> string { return cn_ast.name; }
70
71auto Fn::ast() -> ast::Stmt& {
72 return *def.visit([](auto* ast) -> ast::Stmt* { return ast; });
73}
74auto Fn::ast() const -> const ast::Stmt& {
75 return *def.visit([](auto* ast) -> const ast::Stmt* { return ast; });
76}
77
78auto Fn::ret() const -> optional<ty::Type> {
79 return def.visit([this](ast::CtorDecl* /*ctor*/) { return self_ty; },
80 [](auto* ast) -> optional<ty::Type> {
81 if (auto& ret = ast->ret; ret.has_value())
82 return ret->val_ty();
83 return {};
84 });
85}
86
87auto Fn::arg_count() const -> size_t {
88 return def.visit([](auto* decl) { return decl->args.size(); });
89}
90
91auto Fn::arg_types() const -> vector<ty::Type> { return visit_map_args(fwd<&ast::TypeName::ensure_ty, ty::Type>); }
92auto Fn::arg_names() const -> vector<string> { return visit_map_args(fwd<&ast::TypeName::name, string>); }
93auto Fn::arg_nodes() const -> const vector<ast::TypeName>& {
94 return def.visit([](auto* ast) -> const auto& { return ast->args; });
95}
96auto Fn::args() const -> vector<FnArg> {
97 return visit_map_args([](auto& arg) { return FnArg(arg.ensure_ty(), arg.name, arg); });
98}
99
100auto Fn::varargs() const -> bool {
101 return def.visit([](ast::FnDecl* fn) { return fn->varargs(); }, always_false);
102}
103auto Fn::primitive() const -> bool {
104 return def.visit([](ast::FnDecl* fn) { return fn->primitive(); }, always_false);
105}
106auto Fn::abstract() const -> bool {
107 return def.visit([](ast::FnDecl* fn) { return fn->abstract(); }, always_false);
108}
109auto Fn::extern_decl() const -> bool {
110 return def.visit([](ast::FnDecl* fn) { return fn->extern_decl(); }, always_false);
111}
112auto Fn::local() const -> bool {
113 return def.visit([](ast::LambdaExpr* /* lambda */) { return true; }, always_false);
114}
115auto Fn::extern_linkage() const -> bool {
116 return def.visit([](ast::FnDecl* fn) { return fn->extern_linkage(); }, always_false);
117}
118auto Fn::has_annotation(const string& name) const -> bool {
119 return def.visit([](ast::CtorDecl* /*ctor*/) { return false; },
120 [&name](auto* ast) { return ast->annotations.contains(name); });
121}
122
123void Fn::make_extern_linkage(bool value) {
124 def.visit([value](ast::FnDecl* fn) { return fn->make_extern_linkage(value); },
125 always_throw<"Cannot make non-function declaration external">);
126}
127
129 return def.visit([](ast::FnDecl* fn_decl) -> auto& { return get<ast::Compound>(fn_decl->body); },
130 [](ast::CtorDecl* ct_decl) -> auto& { return ct_decl->body; },
131 [](ast::LambdaExpr* lambda) -> auto& { return lambda->body; });
132}
133
135 return def.visit([](ast::FnDecl* fn_decl) -> auto& { return fn_decl->body; },
136 always_throw<"Cannot get the function body of non-function declaration", ast::FnDecl::Body&>);
137}
138} // namespace yume
virtual void visit(Visitor &visitor) const =0
Recursively visit this ast node and all its constituents.
Statements make up most things in source code.
Definition: ast.hpp:297
Definition: ast.cpp:8
static constexpr const auto fwd< pm, void >
Definition: vals.cpp:18
static constexpr const auto always_throw
Definition: vals.cpp:12
static constexpr const auto always_false
Definition: vals.cpp:9
static constexpr const auto fwd
Definition: vals.cpp:16
auto name() const noexcept -> string
Definition: vals.cpp:69
ast::ConstDecl & cn_ast
Definition: vals.hpp:175
A function declaration in the compiler.
Definition: vals.hpp:52
optional< ty::Type > self_ty
If this function is in the body of a struct, this points to its type. Used for the self type.
Definition: vals.hpp:57
auto arg_names() const -> vector< string >
Definition: vals.cpp:92
auto fn_body() -> ast::FnDecl::Body &
Definition: vals.cpp:134
auto create_instantiation(Substitutions &subs) noexcept -> Fn &
Definition: vals.cpp:20
auto primitive() const -> bool
Definition: vals.cpp:103
auto compound_body() -> ast::Compound &
Definition: vals.cpp:128
auto local() const -> bool
Definition: vals.cpp:112
Def def
The ast node that defines this declaration.
Definition: vals.hpp:54
auto extern_decl() const -> bool
Definition: vals.cpp:109
auto arg_types() const -> vector< ty::Type >
Definition: vals.cpp:91
auto extern_linkage() const -> bool
Definition: vals.cpp:115
auto varargs() const -> bool
Definition: vals.cpp:100
auto abstract() const -> bool
Definition: vals.cpp:106
auto args() const -> vector< FnArg >
Definition: vals.cpp:96
auto arg_count() const -> size_t
Definition: vals.cpp:87
auto ast() const -> const ast::Stmt &
Definition: vals.cpp:74
void make_extern_linkage(bool value=true)
Definition: vals.cpp:123
auto has_annotation(const string &name) const -> bool
Definition: vals.cpp:118
auto arg_nodes() const -> const vector< ast::TypeName > &
Definition: vals.cpp:93
auto ret() const -> optional< ty::Type >
Definition: vals.cpp:78
auto name() const noexcept -> string
Definition: vals.cpp:64
auto get_or_create_instantiation(Substitutions &subs) noexcept -> std::pair< bool, Fn & >
Definition: vals.cpp:36
A struct declaration in the compiler.
Definition: vals.hpp:136
auto name() const noexcept -> string
Definition: vals.cpp:68
ast::StructDecl & st_ast
Definition: vals.hpp:137
auto body() const noexcept -> const auto &
Definition: vals.hpp:160
auto get_or_create_instantiation(Substitutions &subs) noexcept -> std::pair< bool, Struct & >
Definition: vals.cpp:56
auto create_instantiation(Substitutions &subs) noexcept -> Struct &
Definition: vals.cpp:44
A statement consisting of multiple other statements, i.e. the body of a function.
Definition: ast.hpp:712
void visit(Visitor &visitor) const override
Recursively visit this ast node and all its constituents.
Definition: visit.cpp:122
A declaration of a custom constructor (def :new).
Definition: ast.hpp:832
A declaration of a function (def).
Definition: ast.hpp:762
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
auto extern_decl() const -> bool
Definition: ast.hpp:801
auto primitive() const -> bool
Definition: ast.hpp:800
auto abstract() const -> bool
Definition: ast.hpp:802
A local definition of an anonymous function.
Definition: ast.hpp:729
auto visit(Us... us) -> decltype(auto)
Definition: util.hpp:55