summaryrefslogtreecommitdiff
path: root/src/types.hpp
blob: 7e478df5f5f7949e299515aba1e170297a421c82 (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
#ifndef TYPES_HPP_INCLUDED
#define TYPES_HPP_INCLUDED

#include <memory>

#include "common.hpp"
#include "coretypes.hpp"
#include "ast/path.hpp"
#include <serialise.hpp>

namespace AST {
class ExprNode;
class Expr;
}

class TypeRef:
    public Serialisable
{
    enum Class {
        ANY,
        UNIT,
        PRIMITIVE,
        TUPLE,
        REFERENCE,
        POINTER,
        ARRAY,
        GENERIC,
        PATH,
        ASSOCIATED,
    };
    
    Class   m_class;
    enum eCoreType  m_core_type;
    bool    m_is_inner_mutable;
    
    AST::Path   m_path; // local = argument
    ::std::vector<TypeRef>  m_inner_types;
    ::std::shared_ptr<AST::ExprNode>    m_size_expr; //< Can be null (unsized array)
public:
    TypeRef():
        m_class(ANY)
    {}

    struct TagUnit {};  // unit maps to a zero-length tuple, just easier to type
    TypeRef(TagUnit):
        m_class(UNIT)
    {}

    struct TagPrimitive {};
    TypeRef(TagPrimitive, enum eCoreType type):
        m_class(PRIMITIVE),
        m_core_type(type)
    {}
    struct TagTuple {};
    TypeRef(TagTuple _, ::std::vector<TypeRef> inner_types):
        m_class(TUPLE),
        m_inner_types( ::std::move(inner_types) )
    {}
    struct TagReference {};
    TypeRef(TagReference _, bool is_mut, TypeRef inner_type):
        m_class(REFERENCE),
        m_is_inner_mutable(is_mut),
        m_inner_types({::std::move(inner_type)})
    {}
    struct TagPointer {};
    TypeRef(TagPointer _, bool is_mut, TypeRef inner_type):
        m_class(POINTER),
        m_is_inner_mutable(is_mut),
        m_inner_types({::std::move(inner_type)})
    {}
    struct TagSizedArray {};
    TypeRef(TagSizedArray _, TypeRef inner_type, ::std::shared_ptr<AST::ExprNode> size):
        m_class(ARRAY),
        m_inner_types({::std::move(inner_type)}),
        m_size_expr( ::std::move(size) )
    {}
    struct TagUnsizedArray {};
    TypeRef(TagUnsizedArray _, TypeRef inner_type):
        m_class(ARRAY),
        m_inner_types({::std::move(inner_type)})
    {}

    struct TagArg {};
    TypeRef(TagArg, ::std::string name):
        m_class(GENERIC),
        m_path({AST::PathNode(name, {})})
    {}
    TypeRef(::std::string name):
        TypeRef(TagArg(), ::std::move(name))
    {}

    struct TagPath {};
    TypeRef(TagPath, AST::Path path):
        m_class(PATH),
        m_path( ::std::move(path) )
    {}
    TypeRef(AST::Path path):
        TypeRef(TagPath(), ::std::move(path))
    {}
   
    struct TagAssoc {};
    TypeRef(TagAssoc, TypeRef base, TypeRef trait, ::std::string assoc_name):
        TypeRef(::std::move(base), ::std::move(trait), ::std::move(assoc_name))
    {}
    TypeRef(TypeRef base, TypeRef trait, ::std::string assoc_name):
        m_class(ASSOCIATED),
        m_path( {AST::PathNode(assoc_name, {})} ),
        m_inner_types( {::std::move(base), ::std::move(trait)} )
    {}
   
    bool is_wildcard() const { return m_class == ANY; }
    bool is_path() const { return m_class == PATH; }
    bool is_type_param() const { return m_class == GENERIC; }
    AST::Path& path() { assert(is_path()); return m_path; }
    const ::std::string& type_param() const { assert(is_type_param()); return m_path[0].name(); }
    ::std::vector<TypeRef>& sub_types() { return m_inner_types; }
   
    bool operator==(const TypeRef& x) const;
    bool operator!=(const TypeRef& x) const {
        return !(*this == x);
    }
     
    friend ::std::ostream& operator<<(::std::ostream& os, const TypeRef& tr);
    
    static const char* class_name(TypeRef::Class c);
    friend void operator>>(::Deserialiser& d, TypeRef::Class& c);
   
    SERIALISABLE_PROTOTYPES(); 
};

#endif // TYPES_HPP_INCLUDED