summaryrefslogtreecommitdiff
path: root/src/hir_typeck/common.hpp
blob: 9d662100f6144a45109daf286a9d7f45eb782c0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
 * MRustC - Rust Compiler
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * hir_typeck/common.hpp
 * - Typecheck common methods
 */
#pragma once

#include "impl_ref.hpp"
#include <hir/generic_params.hpp>
#include <hir/type.hpp>

// TODO/NOTE - This is identical to ::HIR::t_cb_resolve_type
typedef ::std::function<const ::HIR::TypeRef&(const ::HIR::TypeRef&)>   t_cb_generic;

extern bool monomorphise_type_needed(const ::HIR::TypeRef& tpl);
extern bool monomorphise_pathparams_needed(const ::HIR::PathParams& tpl);
static inline bool monomorphise_genericpath_needed(const ::HIR::GenericPath& tpl) {
    return monomorphise_pathparams_needed(tpl.m_params);
}
extern bool monomorphise_path_needed(const ::HIR::Path& tpl);
extern bool monomorphise_traitpath_needed(const ::HIR::TraitPath& tpl);
extern bool monomorphise_type_needed(const ::HIR::TypeRef& tpl);
extern ::HIR::PathParams monomorphise_path_params_with(const Span& sp, const ::HIR::PathParams& tpl, t_cb_generic callback, bool allow_infer);
extern ::HIR::GenericPath monomorphise_genericpath_with(const Span& sp, const ::HIR::GenericPath& tpl, t_cb_generic callback, bool allow_infer);
extern ::HIR::TraitPath monomorphise_traitpath_with(const Span& sp, const ::HIR::TraitPath& tpl, t_cb_generic callback, bool allow_infer);
extern ::HIR::Path monomorphise_path_with(const Span& sp, const ::HIR::Path& tpl, t_cb_generic callback, bool allow_infer);
extern ::HIR::TypeRef monomorphise_type_with(const Span& sp, const ::HIR::TypeRef& tpl, t_cb_generic callback, bool allow_infer=true);
extern ::HIR::TypeRef monomorphise_type(const Span& sp, const ::HIR::GenericParams& params_def, const ::HIR::PathParams& params,  const ::HIR::TypeRef& tpl);

// Wrappers to only monomorphise if required
static inline const ::HIR::TypeRef& monomorphise_type_with_opt(const Span& sp, ::HIR::TypeRef& tmp, const ::HIR::TypeRef& tpl, t_cb_generic callback, bool allow_infer=true) {
    return (monomorphise_type_needed(tpl) ? tmp = monomorphise_type_with(sp, tpl, callback, allow_infer) : tpl);
}
static inline const ::HIR::Path& monomorphise_path_with_opt(const Span& sp, ::HIR::Path& tmp, const ::HIR::Path& tpl, t_cb_generic callback, bool allow_infer=true) {
    return (monomorphise_path_needed(tpl) ? tmp = monomorphise_path_with(sp, tpl, callback, allow_infer) : tpl);
}
static inline const ::HIR::GenericPath& monomorphise_genericpath_with_opt(const Span& sp, ::HIR::GenericPath& tmp, const ::HIR::GenericPath& tpl, t_cb_generic callback, bool allow_infer=true) {
    return (monomorphise_genericpath_needed(tpl) ? tmp = monomorphise_genericpath_with(sp, tpl, callback, allow_infer) : tpl);
}
static inline const ::HIR::TraitPath& monomorphise_traitpath_with_opt(const Span& sp, ::HIR::TraitPath& tmp, const ::HIR::TraitPath& tpl, t_cb_generic callback, bool allow_infer=true) {
    return (monomorphise_traitpath_needed(tpl) ? tmp = monomorphise_traitpath_with(sp, tpl, callback, allow_infer) : tpl);
}
static inline const ::HIR::PathParams& monomorphise_pathparams_with_opt(const Span& sp, ::HIR::PathParams& tmp, const ::HIR::PathParams& tpl, t_cb_generic callback, bool allow_infer=true) {
    return (monomorphise_pathparams_needed(tpl) ? tmp = monomorphise_path_params_with(sp, tpl, callback, allow_infer) : tpl);
}

typedef ::std::function<bool(const ::HIR::TypeRef&)> t_cb_visit_ty;
/// Calls the provided callback on every type seen when recursing the type.
/// If the callback returns `true`, no further types are visited and the function returns `true`.
extern bool visit_ty_with(const ::HIR::TypeRef& ty, t_cb_visit_ty callback);
extern bool visit_path_tys_with(const ::HIR::Path& ty, t_cb_visit_ty callback);

typedef ::std::function<bool(const ::HIR::TypeRef&, ::HIR::TypeRef&)>   t_cb_clone_ty;
/// Clones a type, calling the provided callback on every type (optionally providing a replacement)
extern ::HIR::TypeRef clone_ty_with(const Span& sp, const ::HIR::TypeRef& tpl, t_cb_clone_ty callback);
extern ::HIR::PathParams clone_path_params_with(const Span& sp, const ::HIR::PathParams& tpl, t_cb_clone_ty callback);

// Helper for passing a group of params around
struct MonomorphState
{
    const ::HIR::TypeRef*   self_ty;
    const ::HIR::PathParams*    pp_impl;
    const ::HIR::PathParams*    pp_method;

    ::HIR::PathParams   pp_impl_data;

    MonomorphState():
        self_ty(nullptr),
        pp_impl(nullptr),
        pp_method(nullptr)
    {
    }
    MonomorphState(MonomorphState&& x):
        MonomorphState()
    {
        *this = ::std::move(x);
    }

    MonomorphState& operator=(MonomorphState&& x) {
        this->self_ty = x.self_ty;
        this->pp_impl = (x.pp_impl == &x.pp_impl_data ? &this->pp_impl_data : x.pp_impl);
        this->pp_method = x.pp_method;
        this->pp_impl_data = ::std::move(x.pp_impl_data);
        return *this;
    }
    MonomorphState clone() const {
        MonomorphState  rv;
        rv.self_ty = this->self_ty;
        rv.pp_impl = (this->pp_impl == &this->pp_impl_data ? &rv.pp_impl_data : this->pp_impl);
        rv.pp_method = this->pp_method;
        rv.pp_impl_data = this->pp_impl_data.clone();
        return rv;
    }

    t_cb_generic    get_cb(const Span& sp) const;

    ::HIR::TypeRef  monomorph(const Span& sp, const ::HIR::TypeRef& ty, bool allow_infer=true) const {
        return monomorphise_type_with(sp, ty, this->get_cb(sp), allow_infer);
    }
    ::HIR::Path monomorph(const Span& sp, const ::HIR::Path& tpl, bool allow_infer=true) const {
        return monomorphise_path_with(sp, tpl, this->get_cb(sp), allow_infer);
    }
};
extern ::std::ostream& operator<<(::std::ostream& os, const MonomorphState& ms);

static inline t_cb_generic monomorphise_type_get_cb(const Span& sp, const ::HIR::TypeRef* self_ty, const ::HIR::PathParams* params_i, const ::HIR::PathParams* params_m, const ::HIR::PathParams* params_p=nullptr)
{
    return [=](const ::HIR::TypeRef& gt)->const ::HIR::TypeRef& {
        const auto& ge = gt.m_data.as_Generic();
        if( ge.binding == 0xFFFF ) {
            ASSERT_BUG(sp, self_ty, "Self wasn't expected here");
            return *self_ty;
        }
        else if( (ge.binding >> 8) == 0 ) {
            auto idx = ge.binding & 0xFF;
            ASSERT_BUG(sp, params_i, "Impl-level params were not expected - " << gt);
            ASSERT_BUG(sp, idx < params_i->m_types.size(), "Parameter out of range " << gt << " >= " << params_i->m_types.size());
            return params_i->m_types[idx];
        }
        else if( (ge.binding >> 8) == 1 ) {
            auto idx = ge.binding & 0xFF;
            ASSERT_BUG(sp, params_m, "Method-level params were not expected - " << gt);
            ASSERT_BUG(sp, idx < params_m->m_types.size(), "Parameter out of range " << gt << " >= " << params_m->m_types.size());
            return params_m->m_types[idx];
        }
        else if( (ge.binding >> 8) == 2 ) {
            auto idx = ge.binding & 0xFF;
            ASSERT_BUG(sp, params_p, "Placeholder params were not expected - " << gt);
            ASSERT_BUG(sp, idx < params_p->m_types.size(), "Parameter out of range " << gt << " >= " << params_p->m_types.size());
            return params_p->m_types[idx];
        }
        else {
            BUG(sp, "Invalid generic type - " << gt);
        }
        };
}

extern void check_type_class_primitive(const Span& sp, const ::HIR::TypeRef& type, ::HIR::InferClass ic, ::HIR::CoreType ct);

class StaticTraitResolve;
extern void Typecheck_Expressions_ValidateOne(const StaticTraitResolve& resolve, const ::std::vector<::std::pair< ::HIR::Pattern, ::HIR::TypeRef>>& args, const ::HIR::TypeRef& ret_ty, const ::HIR::ExprPtr& code);