summaryrefslogtreecommitdiff
path: root/src/hir/pattern.hpp
blob: 136bd5877efdaf00b72c20cc0dffca8b98723b9d (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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*
 * MRustC - Rust Compiler
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * hir/pattern.hpp
 * - HIR Representation of patterns
 */
#pragma once

#include <memory>
#include <vector>
#include <tagged_union.hpp>
#include <hir/path.hpp>
#include <hir/type.hpp>

namespace HIR {

class Struct;
class Enum;
class Constant;

struct PatternBinding
{
    enum class Type {
        Move,
        Ref,
        MutRef,
    };

    bool    m_mutable;
    Type    m_type;
    RcString    m_name;
    unsigned int    m_slot;

    unsigned m_implicit_deref_count = 0;

    bool is_valid() const { return m_name != ""; }

    PatternBinding():
        m_mutable(false),
        m_type(Type::Move),
        m_name(""),
        m_slot(0),
        m_implicit_deref_count(0)
    {}
    PatternBinding(bool mut, Type type, RcString name, unsigned int slot):
        m_mutable(mut),
        m_type(type),
        m_name( mv$(name) ),
        m_slot( slot ),
        m_implicit_deref_count(0)
    {}
};

struct Pattern
{
    TAGGED_UNION(Value, String,
        (Integer, struct {
            ::HIR::CoreType type;  // Str == _
            uint64_t value; // Signed numbers are encoded as 2's complement
            }),
        (Float, struct {
            ::HIR::CoreType type;  // Str == _
            double value;
            }),
        (String, ::std::string),
        (ByteString, struct { ::std::string v; }),
        (Named, struct {
            Path    path;
            const ::HIR::Constant*  binding;
            })
        );
    friend ::std::ostream& operator<<(::std::ostream& os, const Pattern::Value& x);

    enum class GlobPos {
        None,
        Start,
        End,
    };

    TAGGED_UNION(Data, Any,
        // Irrefutable / destructuring
        (Any,       struct { } ),
        (Box,       struct { ::std::unique_ptr<Pattern> sub; }),
        (Ref,       struct { ::HIR::BorrowType type; ::std::unique_ptr<Pattern> sub; } ),
        (Tuple,     struct {
            ::std::vector<Pattern> sub_patterns;
            }),
        (SplitTuple, struct {
            ::std::vector<Pattern> leading;
            ::std::vector<Pattern> trailing;
            unsigned int total_size;
            }),
        (StructValue, struct {
            GenericPath path;
            const Struct*   binding;
            }),
        (StructTuple, struct {
            // NOTE: Type paths in patterns _can_ have parameters
            GenericPath path;
            const Struct*   binding;
            ::std::vector<Pattern> sub_patterns;
            } ),
        (Struct,    struct {
            GenericPath path;
            const Struct*   binding;
            ::std::vector< ::std::pair<RcString, Pattern> > sub_patterns;
            bool is_exhaustive;

            bool is_wildcard() const {
                return sub_patterns.empty() && !is_exhaustive;
            }
            } ),
        // Refutable
        (Value,     struct { Value val; } ),
        (Range,     struct { Value start; Value end; } ),
        (EnumValue, struct {
            GenericPath path;
            const Enum* binding_ptr;
            unsigned binding_idx;
            } ),
        (EnumTuple, struct {
            GenericPath path;
            const Enum* binding_ptr;
            unsigned binding_idx;
            ::std::vector<Pattern> sub_patterns;
            } ),
        (EnumStruct, struct {
            GenericPath path;
            const Enum* binding_ptr;
            unsigned binding_idx;
            ::std::vector< ::std::pair<RcString, Pattern> > sub_patterns;
            bool is_exhaustive;
            } ),
        (Slice,     struct {
            ::std::vector<Pattern> sub_patterns;
            } ),
        (SplitSlice, struct {
            ::std::vector<Pattern> leading;
            PatternBinding extra_bind;
            ::std::vector<Pattern> trailing;
            } )
        );

    PatternBinding  m_binding;
    Data    m_data;
    unsigned m_implicit_deref_count = 0;

    Pattern() {}
    Pattern(PatternBinding pb, Data d):
        m_binding( mv$(pb) ),
        m_data( mv$(d) )
    {}
    Pattern(const Pattern&) = delete;
    Pattern(Pattern&&) = default;
    Pattern& operator=(const Pattern&) = delete;
    Pattern& operator=(Pattern&&) = default;

    Pattern clone() const;

    friend ::std::ostream& operator<<(::std::ostream& os, const Pattern& x);
};

}