summaryrefslogtreecommitdiff
path: root/src/types.hpp
blob: 4ef246853e50e52a4b3e79622ccde90eb5cffb57 (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
#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,
    };
    
    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))
    {}
   
    bool is_path() const { return m_class == PATH; }
    AST::Path& path() { assert(is_path()); return m_path; }
    ::std::vector<TypeRef>& sub_types() { return m_inner_types; }
    
    friend ::std::ostream& operator<<(::std::ostream& os, const TypeRef& tr);
   
    SERIALISABLE_PROTOTYPES(); 
};

#endif // TYPES_HPP_INCLUDED