1 | //
|
---|
2 | // Cforall Version 1.0.0 Copyright (C) 2019 University of Waterloo
|
---|
3 | //
|
---|
4 | // The contents of this file are covered under the licence agreement in the
|
---|
5 | // file "LICENCE" distributed with Cforall.
|
---|
6 | //
|
---|
7 | // Chain.hpp --
|
---|
8 | //
|
---|
9 | // Author : Thierry Delisle
|
---|
10 | // Created On : Wed Jun 05 14:11:52 2019
|
---|
11 | // Last Modified By :
|
---|
12 | // Last Modified On :
|
---|
13 | // Update Count :
|
---|
14 | //
|
---|
15 |
|
---|
16 | #include "Node.hpp"
|
---|
17 |
|
---|
18 | namespace ast {
|
---|
19 |
|
---|
20 | template<typename T>
|
---|
21 | struct _chain_mutator;
|
---|
22 |
|
---|
23 | template<typename node_t, Node::ref_type ref_t>
|
---|
24 | struct _chain_mutator<ptr_base<node_t, ref_t>>;
|
---|
25 |
|
---|
26 | template<template <class...> class container_t, typename node_t, Node::ref_type ref_t>
|
---|
27 | struct _chain_mutator<container_t<ptr_base<node_t, ref_t>>>;
|
---|
28 |
|
---|
29 | template<typename node_t, Node::ref_type ref_t>
|
---|
30 | struct _chain_mutator<ptr_base<node_t, ref_t>> {
|
---|
31 | ptr_base<node_t, ref_t> & base;
|
---|
32 |
|
---|
33 | template<typename actual_node_t, typename child_t>
|
---|
34 | auto operator()( child_t actual_node_t::*child ) {
|
---|
35 | auto n = mutate(base.get());
|
---|
36 | actual_node_t * node = strict_dynamic_cast<actual_node_t *>(n);
|
---|
37 | base = node;
|
---|
38 | return _chain_mutator< typename std::remove_reference< decltype(node->*child) >::type >{node->*child};
|
---|
39 | }
|
---|
40 |
|
---|
41 | node_t * operator->() {
|
---|
42 | auto n = mutate(base.get());
|
---|
43 | base = n;
|
---|
44 | return n;
|
---|
45 | }
|
---|
46 | };
|
---|
47 |
|
---|
48 | template<template <class...> class container_t, typename node_t, Node::ref_type ref_t>
|
---|
49 | struct _chain_mutator<container_t<ptr_base<node_t, ref_t>>> {
|
---|
50 | container_t<ptr_base<node_t, ref_t>> & base;
|
---|
51 |
|
---|
52 | auto operator[]( size_t i ) {
|
---|
53 | return _chain_mutator<ptr_base<node_t, ref_t>>{base[i]};
|
---|
54 | }
|
---|
55 | };
|
---|
56 |
|
---|
57 |
|
---|
58 | template< typename node_t, Node::ref_type ref_t >
|
---|
59 | auto chain_mutate( ptr_base<node_t, ref_t> & base ) {
|
---|
60 | return _chain_mutator<ptr_base<node_t, ref_t>>{ base };
|
---|
61 | }
|
---|
62 |
|
---|
63 | }
|
---|