]>
Commit | Line | Data |
---|---|---|
b37bf2e1 A |
1 | /* |
2 | * This file is part of the KDE libraries | |
3 | * Copyright (C) 2003 Apple Computer, Inc. | |
4 | * | |
5 | * This library is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU Library General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2 of the License, or (at your option) any later version. | |
9 | * | |
10 | * This library is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * Library General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Library General Public License | |
16 | * along with this library; see the file COPYING.LIB. If not, write to | |
17 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
18 | * Boston, MA 02110-1301, USA. | |
19 | * | |
20 | */ | |
21 | ||
22 | #ifndef KJS_SCOPE_CHAIN_H | |
23 | #define KJS_SCOPE_CHAIN_H | |
24 | ||
25 | #include <wtf/Assertions.h> | |
26 | ||
27 | namespace KJS { | |
28 | ||
29 | class JSObject; | |
30 | class ExecState; | |
31 | ||
32 | class ScopeChainNode { | |
33 | public: | |
34 | ScopeChainNode(ScopeChainNode *n, JSObject *o) | |
35 | : next(n), object(o), refCount(1) { } | |
36 | ||
37 | ScopeChainNode *next; | |
38 | JSObject *object; | |
39 | int refCount; | |
40 | }; | |
41 | ||
42 | class ScopeChainIterator { | |
43 | public: | |
44 | ScopeChainIterator(ScopeChainNode *node) : m_node(node) {} | |
45 | ||
46 | JSObject * const & operator*() const { return m_node->object; } | |
47 | JSObject * const * operator->() const { return &(operator*()); } | |
48 | ||
49 | ScopeChainIterator& operator++() { m_node = m_node->next; return *this; } | |
50 | ||
51 | // postfix ++ intentionally omitted | |
52 | ||
53 | bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; } | |
54 | bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; } | |
55 | ||
56 | private: | |
57 | ScopeChainNode *m_node; | |
58 | }; | |
59 | ||
60 | class ScopeChain { | |
61 | public: | |
62 | typedef ScopeChainIterator const_iterator; | |
63 | typedef JSObject* ValueType; | |
64 | ||
65 | ScopeChain() : _node(0) { } | |
66 | ~ScopeChain() { deref(); } | |
67 | ||
68 | ScopeChain(const ScopeChain &c) : _node(c._node) | |
69 | { if (_node) ++_node->refCount; } | |
70 | ScopeChain &operator=(const ScopeChain &); | |
71 | ||
72 | bool isEmpty() const { return !_node; } | |
73 | JSObject *top() const { return _node->object; } | |
74 | ||
75 | JSObject *bottom() const; | |
76 | ||
77 | ScopeChainIterator begin() const { return ScopeChainIterator(_node); } | |
78 | ScopeChainIterator end() const { return ScopeChainIterator(0); } | |
79 | ||
80 | void clear() { deref(); _node = 0; } | |
81 | void push(JSObject *); | |
82 | void push(const ScopeChain &); | |
83 | void replaceTop(JSObject*); | |
84 | void pop(); | |
85 | ||
86 | void mark(); | |
87 | ||
88 | #ifndef NDEBUG | |
89 | void print(); | |
90 | #endif | |
91 | ||
92 | private: | |
93 | ScopeChainNode *_node; | |
94 | ||
95 | void deref() { if (_node && --_node->refCount == 0) release(); } | |
96 | void ref() const; | |
97 | ||
98 | void release(); | |
99 | }; | |
100 | ||
101 | inline void ScopeChain::ref() const | |
102 | { | |
103 | for (ScopeChainNode *n = _node; n; n = n->next) { | |
104 | if (n->refCount++ != 0) | |
105 | break; | |
106 | } | |
107 | } | |
108 | ||
109 | inline ScopeChain &ScopeChain::operator=(const ScopeChain &c) | |
110 | { | |
111 | c.ref(); | |
112 | deref(); | |
113 | _node = c._node; | |
114 | return *this; | |
115 | } | |
116 | ||
117 | inline JSObject *ScopeChain::bottom() const | |
118 | { | |
119 | ScopeChainNode *last = 0; | |
120 | for (ScopeChainNode *n = _node; n; n = n->next) | |
121 | last = n; | |
122 | if (!last) | |
123 | return 0; | |
124 | return last->object; | |
125 | } | |
126 | ||
127 | inline void ScopeChain::push(JSObject *o) | |
128 | { | |
129 | ASSERT(o); | |
130 | _node = new ScopeChainNode(_node, o); | |
131 | } | |
132 | ||
133 | inline void ScopeChain::replaceTop(JSObject* o) | |
134 | { | |
135 | ASSERT(o); | |
136 | _node->object = o; | |
137 | } | |
138 | ||
139 | inline void ScopeChain::pop() | |
140 | { | |
141 | ScopeChainNode *oldNode = _node; | |
142 | ASSERT(oldNode); | |
143 | ScopeChainNode *newNode = oldNode->next; | |
144 | _node = newNode; | |
145 | ||
146 | if (--oldNode->refCount != 0) { | |
147 | if (newNode) | |
148 | ++newNode->refCount; | |
149 | } else { | |
150 | delete oldNode; | |
151 | } | |
152 | } | |
153 | ||
154 | } // namespace KJS | |
155 | ||
156 | #endif // KJS_SCOPE_CHAIN_H |