source: src/AST/Node.hpp@ 2ed1d50

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 2ed1d50 was 6a625de, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Some clean-up, some more assertions to check assumptions and changes to node.hpp

  • Property mode set to 100644
File size: 3.1 KB
RevLine 
[cedb545]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
[6a625de]34 template<typename node_t>
35 friend auto mutate(const node_t * node);
36
[cedb545]37 private:
38 size_t strong_ref = 0;
39 size_t weak_ref = 0;
40 };
41
[6a625de]42 // Mutate a node, non-member function to avoid static type
43 // problems and be able to use auto return
44 template<typename node_t>
45 auto mutate(const node_t * node) {
46 assertf(
47 node->strong_count >= 1,
48 "Error: attempting to mutate a node that appears to have been linked"
49 );
50 if (node->strong_count == 1) {
51 return const_cast<node_t *>(node);
52 }
53
54 assertf(
55 node->weak_count == 0,
56 "Error: mutating node with weak references to it will invalided some references"
57 );
58 return node->clone();
59 }
60
61 // All accept routines should look as follows :
62 // virtual void accept( Visitor &v ) override {
63 // return v.visit(this);
64 // }
65 // Using the following wrapper to handle the node type
66 template< typename node_t >
67 auto visit_this( visitor & v, node_t * node ) {
68 ptr<node_t> p;
69 p.node = node;
70 auto r = v.visit(p);
71 p.node = nullptr;
72 return r;
73 }
74
75 // Base class for the smart pointer types
76 // should never really be used.
77 template< typename node_t, enum Node::ref_type ref_t>
[cedb545]78 class ptr_base {
79 public:
80 ptr_base() : node(nullptr) {}
81 ptr_base( node_t * n ) : node(n) { if( !node ) node->increment(ref_t); }
82 ~ptr_base() { if( node ) node->decrement(ref_t); }
83
84 template< enum Node::ref_type o_ref_t >
85 ptr_base( const ptr_base<node_t, o_ref_t> & o ) : node(o.node) {
86 if( !node ) return;
87 node->increment(ref_t);
88 }
89
90 template< enum Node::ref_type o_ref_t >
91 ptr_base( ptr_base<node_t, o_ref_t> && o ) : node(o.node) {
92 if( node ) node->increment(ref_t);
93 if( node ) node->decrement(o_ref_t);
94 }
95
96 template< enum Node::ref_type o_ref_t >
97 ptr_base & operator=( const ptr_base<node_t, o_ref_t> & o ) {
98 assign(o.node);
99 return *this;
100 }
101
102 template< enum Node::ref_type o_ref_t >
103 ptr_base & operator=( ptr_base<node_t, o_ref_t> && o ) {
104 if(o.node == node) return *this;
105 assign(o.node);
106 if( node ) node->decrement(o_ref_t);
107 return *this;
108 }
109
110 const node_t * get() const { return node; }
111 const node_t * operator->() const { return node; }
112 const node_t & operator* () const { return *node; }
113 operator bool() const { return node; }
114
115 private:
116 void assign(node_t * other ) {
117 if( other ) other->increment(ref_t);
118 if( node ) node ->decrement(ref_t);
119 node = other;
120 }
121
122 protected:
123 node_t * node;
124 };
125
126 template< typename node_t >
[6a625de]127 using ptr = ptr_base< node_t, Node::ref_type::strong >;
[cedb545]128
129 template< typename node_t >
[6a625de]130 using readonly = ptr_base< node_t, Node::ref_type::weak >;
[cedb545]131}
Note: See TracBrowser for help on using the repository browser.