• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 Google Inc. All rights reserved
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef SYMTAB_H_
16 #define SYMTAB_H_
17 
18 #include <bitset>
19 #include <string>
20 #include <vector>
21 
22 #include "string_piece.h"
23 
24 using namespace std;
25 
26 extern vector<string*>* g_symbols;
27 
28 class Symtab;
29 class Var;
30 
31 class Symbol {
32  public:
Symbol()33   explicit Symbol() : v_(-1) {}
34 
str()35   const string& str() const { return *((*g_symbols)[v_]); }
36 
c_str()37   const char* c_str() const { return str().c_str(); }
38 
empty()39   bool empty() const { return !v_; }
40 
val()41   int val() const { return v_; }
42 
get(size_t i)43   char get(size_t i) const {
44     const string& s = str();
45     if (i >= s.size())
46       return 0;
47     return s[i];
48   }
49 
IsValid()50   bool IsValid() const { return v_ >= 0; }
51 
52   Var* PeekGlobalVar() const;
53   Var* GetGlobalVar() const;
54   void SetGlobalVar(Var* v,
55                     bool is_override = false,
56                     bool* readonly = nullptr) const;
57 
58  private:
59   explicit Symbol(int v);
60 
61   int v_;
62 
63   friend class Symtab;
64   friend class SymbolSet;
65 };
66 
67 /* A set of symbols represented as bitmap indexed by Symbol's ordinal value. */
68 class SymbolSet {
69  public:
SymbolSet()70   SymbolSet() : low_(0), high_(0) {}
71 
72   /* Returns true if Symbol belongs to this set. */
exists(Symbol sym)73   bool exists(Symbol sym) const {
74     size_t bit_nr = static_cast<size_t>(sym.val());
75     return sym.IsValid() && bit_nr >= low_ && bit_nr < high_ &&
76            bits_[(bit_nr - low_) / 64][(bit_nr - low_) % 64];
77   }
78 
79   /* Adds Symbol to this set.  */
insert(Symbol sym)80   void insert(Symbol sym) {
81     if (!sym.IsValid()) {
82       return;
83     }
84     size_t bit_nr = static_cast<size_t>(sym.val());
85     if (bit_nr < low_ || bit_nr >= high_) {
86       resize(bit_nr);
87     }
88     bits_[(bit_nr - low_) / 64][(bit_nr - low_) % 64] = true;
89   }
90 
91   /* Returns the number of Symbol's in this set.  */
size()92   size_t size() const {
93     size_t n = 0;
94     for (auto const& bitset : bits_) {
95       n += bitset.count();
96     }
97     return n;
98   }
99 
100   /* Allow using foreach.
101    * E.g.,
102    *   SymbolSet symbol_set;
103    *   for (auto const& symbol: symbol_set) { ... }
104    */
105   class iterator {
106     const SymbolSet* bitset_;
107     size_t pos_;
108 
iterator(const SymbolSet * bitset,size_t pos)109     iterator(const SymbolSet* bitset, size_t pos)
110         : bitset_(bitset), pos_(pos) {}
111 
112     /* Proceed to the next Symbol.  */
next()113     void next() {
114       size_t bit_nr = (pos_ > bitset_->low_) ? pos_ - bitset_->low_ : 0;
115       while (bit_nr < (bitset_->high_ - bitset_->low_)) {
116         if ((bit_nr % 64) == 0 && !bitset_->bits_[bit_nr / 64].any()) {
117           bit_nr += 64;
118           continue;
119         }
120         if (bitset_->bits_[bit_nr / 64][bit_nr % 64]) {
121           break;
122         }
123         ++bit_nr;
124       }
125       pos_ = bitset_->low_ + bit_nr;
126     }
127 
128    public:
129     iterator& operator++() {
130       if (pos_ < bitset_->high_) {
131         ++pos_;
132         next();
133       }
134       return *this;
135     }
136 
137     bool operator==(iterator other) const {
138       return bitset_ == other.bitset_ && pos_ == other.pos_;
139     }
140 
141     bool operator!=(iterator other) const { return !(*this == other); }
142 
143     Symbol operator*() { return Symbol(pos_); }
144 
145     friend class SymbolSet;
146   };
147 
begin()148   iterator begin() const {
149     iterator it(this, low_);
150     it.next();
151     return it;
152   }
153 
end()154   iterator end() const { return iterator(this, high_); }
155 
156  private:
157   friend class iterator;
158 
159   /* Ensure that given bit number is in [low_, high_)  */
resize(size_t bit_nr)160   void resize(size_t bit_nr) {
161     size_t new_low = bit_nr & ~63;
162     size_t new_high = (bit_nr + 64) & ~63;
163     if (bits_.empty()) {
164       high_ = low_ = new_low;
165     }
166     if (new_low > low_) {
167       new_low = low_;
168     }
169     if (new_high <= high_) {
170       new_high = high_;
171     }
172     if (new_low == low_) {
173       bits_.resize((new_high - new_low) / 64);
174     } else {
175       std::vector<std::bitset<64> > newbits((new_high - new_low) / 64);
176       std::copy(bits_.begin(), bits_.end(),
177                 newbits.begin() + (low_ - new_low) / 64);
178       bits_.swap(newbits);
179     }
180     low_ = new_low;
181     high_ = new_high;
182   }
183 
184   /* Keep only the (aligned) range where at least one bit has been set.
185    * E.g., if we only ever set bits 65 and 141, |low_| will be 64, |high_|
186    * will be 192, and |bits_| will have 2 elements.
187    */
188   size_t low_;
189   size_t high_;
190   std::vector<std::bitset<64> > bits_;
191 };
192 
193 class ScopedGlobalVar {
194  public:
195   ScopedGlobalVar(Symbol name, Var* var);
196   ~ScopedGlobalVar();
197 
198  private:
199   Symbol name_;
200   Var* orig_;
201 };
202 
203 inline bool operator==(const Symbol& x, const Symbol& y) {
204   return x.val() == y.val();
205 }
206 
207 inline bool operator<(const Symbol& x, const Symbol& y) {
208   return x.val() < y.val();
209 }
210 
211 namespace std {
212 template <>
213 struct hash<Symbol> {
214   size_t operator()(const Symbol& s) const { return s.val(); }
215 };
216 }  // namespace std
217 
218 extern Symbol kEmptySym;
219 extern Symbol kShellSym;
220 extern Symbol kKatiReadonlySym;
221 
222 void InitSymtab();
223 void QuitSymtab();
224 Symbol Intern(StringPiece s);
225 
226 string JoinSymbols(const vector<Symbol>& syms, const char* sep);
227 
228 #endif  // SYMTAB_H_
229