source: src/AST/Node.hpp @ 6a625de

arm-ehcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 6a625de was 6a625de, checked in by Thierry Delisle <tdelisle@…>, 4 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
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                template<typename node_t>
35                friend auto mutate(const node_t * node);
36
37        private:
38                size_t strong_ref = 0;
39                size_t weak_ref = 0;
40        };
41
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>
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 >
127        using ptr = ptr_base< node_t, Node::ref_type::strong >;
128
129        template< typename node_t >
130        using readonly = ptr_base< node_t, Node::ref_type::weak >;
131}
Note: See TracBrowser for help on using the repository browser.