summaryrefslogtreecommitdiff
path: root/src/third_party/mozjs-60/extract/js/src/ds/Nestable.h
blob: c02264abcea152885565d5b800881f747a5e641c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef ds_Nestable_h
#define ds_Nestable_h

namespace js {

// A base class for nestable structures.
template <typename Concrete>
class MOZ_STACK_CLASS Nestable
{
    Concrete** stack_;
    Concrete*  enclosing_;

  protected:
    explicit Nestable(Concrete** stack)
      : stack_(stack),
        enclosing_(*stack)
    {
        *stack_ = static_cast<Concrete*>(this);
    }

    // These method are protected. Some derived classes, such as ParseContext,
    // do not expose the ability to walk the stack.
    Concrete* enclosing() const {
        return enclosing_;
    }

    template <typename Predicate /* (Concrete*) -> bool */>
    static Concrete* findNearest(Concrete* it, Predicate predicate) {
        while (it && !predicate(it))
            it = it->enclosing();
        return it;
    }

    template <typename T>
    static T* findNearest(Concrete* it) {
        while (it && !it->template is<T>())
            it = it->enclosing();
        return it ? &it->template as<T>() : nullptr;
    }

    template <typename T, typename Predicate /* (T*) -> bool */>
    static T* findNearest(Concrete* it, Predicate predicate) {
        while (it && (!it->template is<T>() || !predicate(&it->template as<T>())))
            it = it->enclosing();
        return it ? &it->template as<T>() : nullptr;
    }

  public:
    ~Nestable() {
        MOZ_ASSERT(*stack_ == static_cast<Concrete*>(this));
        *stack_ = enclosing_;
    }
};

} // namespace js

#endif /* ds_Nestable_h */