Changed several occurrences of Ref<VirtualRegister> or RefOrNull<V..R..>
[jitcs.git] / include / jitcs_adt_ref.h
blob57d0f3899cdaf56bc21b67b66b80000375f4e77a
1 //===-- jitcs_adt_ref.h - pointer helper type -------------------*- C++ -*-===//
2 //
3 // This file contains two pointer types. The first, Ref, represents a single
4 // pointer, which CANNOT be NULL. Data access is possible thru the use of
5 // the -> operator. The second type, RefOrNull, represents a pointer which
6 // CAN be NULL. Access to the pointed-to data by usage of the method
7 // removeNullType. (The principle of this is taken from the language Ceylon
8 // which, according to my understanding, handles null pointer quite nicely.)
9 //
10 //===----------------------------------------------------------------------===//
12 #ifndef _JITCS_ADT_REF_H_
13 #define _JITCS_ADT_REF_H_
15 #include <assert.h>
16 #include <type_traits>
18 namespace jitcs {
19 enum {
20 REF_Any = 0,
21 REF_Nullable = 1,
22 REF_Const = 2,
25 template <bool b, typename = typename std::enable_if<b,int>::type>
26 void guarantee(const char *) {}
28 // _Ref is an attributed pointer type.
29 // Currently it supports the const-attribute of its data, and
30 // the nonnull-attribute of the pointer.
32 template <typename T, unsigned FLAGS>
33 struct _Ref {
34 typedef typename std::add_const<T>::type CType;
35 typedef T NCType;
36 static const bool IsConstRef = (FLAGS & REF_Const) != 0;
37 typedef typename std::conditional<IsConstRef, CType, NCType>::type Type;
38 typedef Type* PtrType;
39 typedef Type& RefType;
41 _Ref() {
42 guarantee<(FLAGS & REF_Nullable) != 0>
43 ("Default constructor only for nullable refs");
44 _ptr = nullptr;
45 _isValid = false;
47 _Ref(const _Ref&) = default;
48 _Ref& operator = (const _Ref&) = default;
49 PtrType ptr() {
50 assert(_isValid);
51 return _ptr;
53 PtrType operator ->() {
54 guarantee<(FLAGS & REF_Nullable) == 0>
55 ("dereferencing only for non-nullable refs, remove nullable first");
56 return ptr();
58 RefType operator *() {
59 guarantee<(FLAGS & REF_Nullable) == 0>
60 ("dereferencing only for non-nullable refs, remove nullable first");
61 return *ptr();
64 template <typename T2, unsigned FLAGS2>
65 _Ref(_Ref<T2, FLAGS2> o) {
66 static_assert((~FLAGS & FLAGS2) == 0, "incompatible _Ref flags");
67 //static_assert(std::is_base_of<T, T2>::value, "incompatible _Ref types");
68 _ptr = o._ptr;
70 template <typename T2>
71 _Ref(T2* o) {
72 typedef typename std::remove_const<T2>::type T2B;
73 //static_assert(std::is_base_of<T, T2B>::value, "incompatible _Ref types");
74 if ((FLAGS & REF_Nullable) == 0)
75 assert(o != nullptr);
76 _ptr = o;
77 _isValid = true;
79 _Ref(std::nullptr_t) {
80 guarantee<(FLAGS & REF_Nullable) != 0>("nullptr not allowed here");
81 _ptr = nullptr;
82 _isValid = true;
85 template <typename T2, unsigned FLAGS2>
86 _Ref& operator =(_Ref<T2, FLAGS2> o) {
87 static_assert((~FLAGS & FLAGS2) == 0, "incompatible _Ref flags");
88 //static_assert(std::is_base_of<T, T2>::value, "incompatible _Ref types");
89 _ptr = o._ptr;
90 _isValid = o._isValid;
92 template <typename T2>
93 _Ref& operator =(T2* o) {
94 typedef typename std::remove_const<T2>::type T2B;
95 //static_assert(std::is_base_of<T, T2B>::value, "incompatible _Ref types");
96 if ((FLAGS & REF_Nullable) == 0)
97 assert(o != nullptr);
98 _ptr = o;
99 _isValid = true;
101 _Ref& operator =(std::nullptr_t) {
102 guarantee<(FLAGS & REF_Nullable) != 0>("nullptr not allowed here");
103 _ptr = nullptr;
104 _isValid = true;
108 bool isNull() const {
109 if ((FLAGS & REF_Nullable) == 0)
110 return false;
111 return _ptr == nullptr;
113 _Ref<T,FLAGS & ~REF_Nullable> removeNullType() const {
114 if ((FLAGS & REF_Nullable) == 0)
115 return _ptr;
116 assert(_ptr != nullptr);
117 return _ptr;
120 PtrType _ptr;
121 bool _isValid;
124 // Ref represents a nonnull pointer to some object.
126 template <typename T>
127 using Ref = _Ref<typename std::remove_const<T>::type,
128 (std::is_const<T>::value ? REF_Const : REF_Any)>;
130 // RefOrNull represents a normal pointer to some object. Accessing the
131 // data is achieved thru removeNullType, after which the "->" operator
132 // is accessible. Calling removeNullType without checking isNull first
133 // is considered a bug.
134 // The concept is taken from the Ceylon language which handles null
135 // pointers very nicely thru a clever type system.
137 template <typename T>
138 using RefOrNull = _Ref<typename std::remove_const<T>::type,
139 (std::is_const<T>::value ? REF_Const : REF_Any)
140 + REF_Nullable>;
141 } // end of namespace jitcs
143 #endif
144 // _JITCS_ADT_REF_H_