source: src/AST/Node.hpp@ cedb545

ADT arm-eh ast-experimental cleanup-dtors enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since cedb545 was cedb545, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Added base class for new AST nodes

  • Property mode set to 100644
File size: 3.7 KB
Line 
1#pragma once
2
3#include <memory>
4
5namespace ast {
6
7 class Node {
8 public:
9 virtual ~Node() = default;
10
11 enum class ref_type {
12 strong,
13 weak
14 };
15
16 void increment(ref_type ref) {
17 switch (ref) {
18 case ref_type::strong: strong_ref++; break;
19 case ref_type::weak : weak_ref ++; break;
20 }
21 }
22
23 void decrement(ref_type ref) {
24 switch (ref) {
25 case ref_type::strong: strong_ref--; break;
26 case ref_type::weak : weak_ref --; break;
27 }
28
29 if(!strong_ref && !weak_ref) {
30 delete this;
31 }
32 }
33
34 private:
35 size_t strong_ref = 0;
36 size_t weak_ref = 0;
37 };
38
39 template< typename node_t, enum Node::ref_type ref_t>
40 class ptr_base {
41 public:
42 ptr_base() : node(nullptr) {}
43 ptr_base( node_t * n ) : node(n) { if( !node ) node->increment(ref_t); }
44 ~ptr_base() { if( node ) node->decrement(ref_t); }
45
46 template< enum Node::ref_type o_ref_t >
47 ptr_base( const ptr_base<node_t, o_ref_t> & o ) : node(o.node) {
48 if( !node ) return;
49 node->increment(ref_t);
50 }
51
52 template< enum Node::ref_type o_ref_t >
53 ptr_base( ptr_base<node_t, o_ref_t> && o ) : node(o.node) {
54 if( node ) node->increment(ref_t);
55 if( node ) node->decrement(o_ref_t);
56 }
57
58 template< enum Node::ref_type o_ref_t >
59 ptr_base & operator=( const ptr_base<node_t, o_ref_t> & o ) {
60 assign(o.node);
61 return *this;
62 }
63
64 template< enum Node::ref_type o_ref_t >
65 ptr_base & operator=( ptr_base<node_t, o_ref_t> && o ) {
66 if(o.node == node) return *this;
67 assign(o.node);
68 if( node ) node->decrement(o_ref_t);
69 return *this;
70 }
71
72 const node_t * get() const { return node; }
73 const node_t * operator->() const { return node; }
74 const node_t & operator* () const { return *node; }
75 operator bool() const { return node; }
76
77 private:
78 void assign(node_t * other ) {
79 if( other ) other->increment(ref_t);
80 if( node ) node ->decrement(ref_t);
81 node = other;
82 }
83
84 protected:
85 node_t * node;
86 };
87
88 template< typename node_t >
89 class ptr : public ptr_base< node_t, Node::ref_type::strong > {
90 public:
91 typedef ptr_base< node_t, Node::ref_type::strong > base_t;
92
93 ptr() = default;
94 ptr( node_t node ) : base_t( node ) {}
95 ~ptr() = default;
96
97 template< enum Node::ref_type ref_t >
98 ptr( const ptr_base<node_t, ref_t> & o ) : base_t(o) {}
99
100 template< enum Node::ref_type ref_t >
101 ptr( ptr_base<node_t, ref_t> && o ) : base_t( std::move(o) ) {}
102
103 template< enum Node::ref_type o_ref_t >
104 ptr & operator=( const ptr_base<node_t, o_ref_t> & o ) {
105 base_t::operator=(o);
106 return *this;
107 }
108
109 template< enum Node::ref_type o_ref_t >
110 ptr & operator=( ptr_base<node_t, o_ref_t> && o ) {
111 base_t::operator=(std::move(o));
112 return *this;
113 }
114
115 node_t * mutate() {
116 using base_t::node;
117 assert(node->strong_count);
118 if (node->strong_count == 1) {
119 return node;
120 }
121
122 assertf(node->weak_count == 0, "Error: mutating node with weak references to it will invalided some references");
123 auto n = new node_t(*node);
124 assign(n);
125 return node;
126 }
127 };
128
129 template< typename node_t >
130 class readonly : public ptr_base< node_t, Node::ref_type::weak > {
131 public:
132 typedef ptr_base< node_t, Node::ref_type::strong > base_t;
133
134 readonly() = default;
135 readonly( node_t node ) : base_t( node ) {}
136 ~readonly() = default;
137
138 template< enum Node::ref_type ref_t >
139 readonly( const ptr_base<node_t, ref_t> & o ) : base_t(o) {}
140
141 template< enum Node::ref_type ref_t >
142 readonly( ptr_base<node_t, ref_t> && o ) : base_t( std::move(o) ) {}
143
144 template< enum Node::ref_type o_ref_t >
145 readonly & operator=( const ptr_base<node_t, o_ref_t> & o ) {
146 base_t::operator=(o);
147 return *this;
148 }
149
150 template< enum Node::ref_type o_ref_t >
151 readonly & operator=( ptr_base<node_t, o_ref_t> && o ) {
152 base_t::operator=(std::move(o));
153 return *this;
154 }
155 };
156}
Note: See TracBrowser for help on using the repository browser.