source: src/AST/Node.hpp @ f47f887

ADTarm-ehast-experimentalcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since f47f887 was f47f887, checked in by Thierry Delisle <tdelisle@…>, 5 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.