source: src/AST/Node.hpp @ cedb545

arm-ehcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-expr
Last change on this file since cedb545 was cedb545, checked in by Thierry Delisle <tdelisle@…>, 3 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.