/* * Copyright (c) 2015 PLUMgrid, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include namespace ebpf { namespace cc { using std::string; using std::vector; using std::map; using std::pair; using std::unique_ptr; class StateDeclStmtNode; class VariableDeclStmtNode; class TableDeclStmtNode; class StructDeclStmtNode; class FuncDeclStmtNode; enum search_type { SCOPE_LOCAL, SCOPE_GLOBAL }; template class Scope { public: Scope() {} Scope(Scope* scope, int id) : parent_(scope), id_(id) {} T* lookup(const string &name, bool search_local = true) { return lookup(name, search_local ? SCOPE_LOCAL : SCOPE_GLOBAL); } T * lookup(const string &name, search_type stype) { auto it = elems_.find(name); if (it != elems_.end()) return it->second; if (stype == SCOPE_LOCAL || !parent_) return nullptr; return parent_->lookup(name, stype); } void add(const string& name, T* n) { elems_[name] = n; elems_ordered_.push_back(n); } typename map::iterator begin() { return elems_.begin(); } typename map::iterator end() { return elems_.end(); } typename vector::iterator obegin() { return elems_ordered_.begin(); } typename vector::iterator oend() { return elems_ordered_.end(); } Scope *parent_; int id_; map elems_; vector elems_ordered_; }; /** * Hold the current stack of scope pointers. Lookups search upwards. * Actual scope pointers are kept in the AST. */ class Scopes { public: typedef unique_ptr Ptr; typedef Scope StructScope; typedef Scope StateScope; typedef Scope VarScope; typedef Scope TableScope; typedef Scope FuncScope; Scopes() : var_id__(0), state_id_(0), var_id_(0), current_var_scope_(nullptr), top_var_scope_(nullptr), current_state_scope_(nullptr), top_state_scope_(nullptr), top_struct_scope_(new StructScope(nullptr, 1)), top_table_scope_(new TableScope(nullptr, 1)), top_func_scope_(new FuncScope(nullptr, 1)) {} ~Scopes() { delete top_func_scope_; delete top_struct_scope_; delete top_table_scope_; delete top_state_scope_; } void push_var(VarScope *scope) { if (scope == top_var_scope_) return; scope->parent_ = current_var_scope_; current_var_scope_ = scope; } void pop_var() { if (current_var_scope_ == top_var_scope_) return; VarScope *old = current_var_scope_; current_var_scope_ = old->parent_; old->parent_ = nullptr; } void push_state(StateScope *scope) { if (scope == top_state_scope_) return; scope->parent_ = current_state_scope_; current_state_scope_ = scope; } void pop_state() { if (current_state_scope_ == top_state_scope_) return; StateScope *old = current_state_scope_; current_state_scope_ = old->parent_; old->parent_ = nullptr; } /// While building the AST, allocate a new scope VarScope* enter_var_scope() { current_var_scope_ = new VarScope(current_var_scope_, next_var_id()); if (!top_var_scope_) { top_var_scope_ = current_var_scope_; } return current_var_scope_; } VarScope* exit_var_scope() { current_var_scope_ = current_var_scope_->parent_; return current_var_scope_; } StateScope* enter_state_scope() { current_state_scope_ = new StateScope(current_state_scope_, next_state_id()); if (!top_state_scope_) { top_state_scope_ = current_state_scope_; } return current_state_scope_; } StateScope* exit_state_scope() { current_state_scope_ = current_state_scope_->parent_; return current_state_scope_; } void set_current(VarScope* s) { current_var_scope_ = s; } VarScope* current_var() const { return current_var_scope_; } VarScope* top_var() const { return top_var_scope_; } void set_current(StateScope* s) { current_state_scope_ = s; } StateScope* current_state() const { return current_state_scope_; } StateScope* top_state() const { return top_state_scope_; } StructScope* top_struct() const { return top_struct_scope_; } TableScope* top_table() const { return top_table_scope_; } FuncScope* top_func() const { return top_func_scope_; } int next_id() { return ++var_id__; } int next_state_id() { return ++state_id_; } int next_var_id() { return ++var_id_; } int var_id__; int state_id_; int var_id_; VarScope* current_var_scope_; VarScope* top_var_scope_; StateScope* current_state_scope_; StateScope* top_state_scope_; StructScope* top_struct_scope_; TableScope* top_table_scope_; FuncScope* top_func_scope_; }; } // namespace cc } // namespace ebpf