• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2015 PLUMgrid, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <map>
20 #include <string>
21 #include <vector>
22 #include <memory>
23 
24 namespace ebpf {
25 namespace cc {
26 
27 using std::string;
28 using std::vector;
29 using std::map;
30 using std::pair;
31 using std::unique_ptr;
32 
33 class StateDeclStmtNode;
34 class VariableDeclStmtNode;
35 class TableDeclStmtNode;
36 class StructDeclStmtNode;
37 class FuncDeclStmtNode;
38 
39 enum search_type { SCOPE_LOCAL, SCOPE_GLOBAL };
40 
41 template <typename T>
42 class Scope {
43  public:
Scope()44   Scope() {}
Scope(Scope<T> * scope,int id)45   Scope(Scope<T>* scope, int id) : parent_(scope), id_(id) {}
46 
47   T* lookup(const string &name, bool search_local = true) {
48     return lookup(name, search_local ? SCOPE_LOCAL : SCOPE_GLOBAL);
49   }
lookup(const string & name,search_type stype)50   T * lookup(const string &name, search_type stype) {
51     auto it = elems_.find(name);
52     if (it != elems_.end())
53       return it->second;
54 
55     if (stype == SCOPE_LOCAL || !parent_)
56       return nullptr;
57     return parent_->lookup(name, stype);
58   }
add(const string & name,T * n)59   void add(const string& name, T* n) {
60     elems_[name] = n;
61     elems_ordered_.push_back(n);
62   }
begin()63   typename map<string, T*>::iterator begin() { return elems_.begin(); }
end()64   typename map<string, T*>::iterator end() { return elems_.end(); }
obegin()65   typename vector<T*>::iterator obegin() { return elems_ordered_.begin(); }
oend()66   typename vector<T*>::iterator oend() { return elems_ordered_.end(); }
67 
68   Scope<T> *parent_;
69   int id_;
70   map<string, T*> elems_;
71   vector<T*> elems_ordered_;
72 };
73 
74 /**
75  * Hold the current stack of scope pointers.  Lookups search upwards.
76  * Actual scope pointers are kept in the AST.
77  */
78 class Scopes {
79  public:
80   typedef unique_ptr<Scopes> Ptr;
81   typedef Scope<StructDeclStmtNode> StructScope;
82   typedef Scope<StateDeclStmtNode> StateScope;
83   typedef Scope<VariableDeclStmtNode> VarScope;
84   typedef Scope<TableDeclStmtNode> TableScope;
85   typedef Scope<FuncDeclStmtNode> FuncScope;
86 
Scopes()87   Scopes() : var_id__(0), state_id_(0), var_id_(0),
88     current_var_scope_(nullptr), top_var_scope_(nullptr),
89     current_state_scope_(nullptr), top_state_scope_(nullptr),
90     top_struct_scope_(new StructScope(nullptr, 1)),
91     top_table_scope_(new TableScope(nullptr, 1)),
92     top_func_scope_(new FuncScope(nullptr, 1)) {}
~Scopes()93   ~Scopes() {
94     delete top_func_scope_;
95     delete top_struct_scope_;
96     delete top_table_scope_;
97     delete top_state_scope_;
98   }
99 
push_var(VarScope * scope)100   void push_var(VarScope *scope) {
101     if (scope == top_var_scope_)
102       return;
103     scope->parent_ = current_var_scope_;
104     current_var_scope_ = scope;
105   }
pop_var()106   void pop_var() {
107     if (current_var_scope_ == top_var_scope_)
108       return;
109     VarScope *old = current_var_scope_;
110     current_var_scope_ = old->parent_;
111     old->parent_ = nullptr;
112   }
113 
push_state(StateScope * scope)114   void push_state(StateScope *scope) {
115     if (scope == top_state_scope_)
116       return;
117     scope->parent_ = current_state_scope_;
118     current_state_scope_ = scope;
119   }
pop_state()120   void pop_state() {
121     if (current_state_scope_ == top_state_scope_)
122       return;
123     StateScope *old = current_state_scope_;
124     current_state_scope_ = old->parent_;
125     old->parent_ = nullptr;
126   }
127 
128   /// While building the AST, allocate a new scope
enter_var_scope()129   VarScope* enter_var_scope() {
130     current_var_scope_ = new VarScope(current_var_scope_, next_var_id());
131     if (!top_var_scope_) {
132       top_var_scope_ = current_var_scope_;
133     }
134     return current_var_scope_;
135   }
136 
exit_var_scope()137   VarScope* exit_var_scope() {
138     current_var_scope_ = current_var_scope_->parent_;
139     return current_var_scope_;
140   }
141 
enter_state_scope()142   StateScope* enter_state_scope() {
143     current_state_scope_ = new StateScope(current_state_scope_, next_state_id());
144     if (!top_state_scope_) {
145       top_state_scope_ = current_state_scope_;
146     }
147     return current_state_scope_;
148   }
149 
exit_state_scope()150   StateScope* exit_state_scope() {
151     current_state_scope_ = current_state_scope_->parent_;
152     return current_state_scope_;
153   }
154 
set_current(VarScope * s)155   void set_current(VarScope* s) { current_var_scope_ = s; }
current_var()156   VarScope* current_var() const { return current_var_scope_; }
top_var()157   VarScope* top_var() const { return top_var_scope_; }
158 
set_current(StateScope * s)159   void set_current(StateScope* s) { current_state_scope_ = s; }
current_state()160   StateScope* current_state() const { return current_state_scope_; }
top_state()161   StateScope* top_state() const { return top_state_scope_; }
162 
top_struct()163   StructScope* top_struct() const { return top_struct_scope_; }
164 
top_table()165   TableScope* top_table() const { return top_table_scope_; }
top_func()166   FuncScope* top_func() const { return top_func_scope_; }
167 
next_id()168   int next_id() { return ++var_id__; }
next_state_id()169   int next_state_id() { return ++state_id_; }
next_var_id()170   int next_var_id() { return ++var_id_; }
171 
172   int var_id__;
173   int state_id_;
174   int var_id_;
175   VarScope* current_var_scope_;
176   VarScope* top_var_scope_;
177   StateScope* current_state_scope_;
178   StateScope* top_state_scope_;
179   StructScope* top_struct_scope_;
180   TableScope* top_table_scope_;
181   FuncScope* top_func_scope_;
182 };
183 
184 }  // namespace cc
185 }  // namespace ebpf
186