source: src/AST/Node.hpp@ f47f887

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 stuck-waitfor-destruct
Last change on this file since f47f887 was f47f887, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

First draft of Pass.hpp and some updates to node.hpp

  • Property mode set to 100644
File size: 2.7 KB
Line 
1#pragma once
2
3#include <memory>
4
5namespace ast {
6class Node {
7public:
8 virtual ~Node() = default;
9
10 enum class ref_type {
11 strong,
12 weak
13 };
14
15 inline void increment(ref_type ref) const {
16 switch (ref) {
17 case ref_type::strong: strong_ref++; break;
18 case ref_type::weak : weak_ref ++; break;
19 }
20 }
21
22 inline void decrement(ref_type ref) const {
23 switch (ref) {
24 case ref_type::strong: strong_ref--; break;
25 case ref_type::weak : weak_ref --; break;
26 }
27
28 if(!strong_ref && !weak_ref) {
29 delete this;
30 }
31 }
32
33 template<typename node_t>
34 friend auto mutate(const node_t * node);
35
36private:
37 mutable size_t strong_ref = 0;
38 mutable size_t weak_ref = 0;
39};
40
41// Mutate a node, non-member function to avoid static type
42// problems and be able to use auto return
43template<typename node_t>
44auto mutate(const node_t * node) {
45 assertf(
46 node->strong_count >= 1,
47 "Error: attempting to mutate a node that appears to have been linked"
48 );
49 if (node->strong_count == 1) {
50 return const_cast<node_t *>(node);
51 }
52
53 assertf(
54 node->weak_count == 0,
55 "Error: mutating node with weak references to it will invalided some references"
56 );
57 return node->clone();
58}
59
60// Base class for the smart pointer types
61// should never really be used.
62template< typename node_t, enum Node::ref_type ref_t>
63class ptr_base {
64public:
65 ptr_base() : node(nullptr) {}
66 ptr_base( node_t * n ) : node(n) { if( !node ) node->increment(ref_t); }
67 ~ptr_base() { if( node ) node->decrement(ref_t); }
68
69 template< enum Node::ref_type o_ref_t >
70 ptr_base( const ptr_base<node_t, o_ref_t> & o ) : node(o.node) {
71 if( !node ) return;
72 node->increment(ref_t);
73 }
74
75 template< enum Node::ref_type o_ref_t >
76 ptr_base( ptr_base<node_t, o_ref_t> && o ) : node(o.node) {
77 if( node ) node->increment(ref_t);
78 if( node ) node->decrement(o_ref_t);
79 }
80
81 template< enum Node::ref_type o_ref_t >
82 ptr_base & operator=( const ptr_base<node_t, o_ref_t> & o ) {
83 assign(o.node);
84 return *this;
85 }
86
87 template< enum Node::ref_type o_ref_t >
88 ptr_base & operator=( ptr_base<node_t, o_ref_t> && o ) {
89 if(o.node == node) return *this;
90 assign(o.node);
91 if( node ) node->decrement(o_ref_t);
92 return *this;
93 }
94
95 const node_t * get() const { return node; }
96 const node_t * operator->() const { return node; }
97 const node_t & operator* () const { return *node; }
98 explicit operator bool() const { return node; }
99 operator const node_t * const() const { return node; }
100
101 using ptr = const node_t *;
102
103private:
104 void assign(node_t * other ) {
105 if( other ) other->increment(ref_t);
106 if( node ) node ->decrement(ref_t);
107 node = other;
108 }
109
110protected:
111 node_t * node;
112};
113
114template< typename node_t >
115using ptr = ptr_base< node_t, Node::ref_type::strong >;
116
117template< typename node_t >
118using readonly = ptr_base< node_t, Node::ref_type::weak >;
119}
Note: See TracBrowser for help on using the repository browser.