blob: 9a68f0772ca9b2b8b5c7b50aaea751c6a6cdb476 [file] [log] [blame]
/*
* ====================================================================
* Copyright (c) 2012, PLUMgrid, http://plumgrid.com
*
* This source is subject to the PLUMgrid License.
* All rights reserved.
*
* THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF
* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
* PARTICULAR PURPOSE.
*
* PLUMgrid confidential information, delete if you are not the
* intended recipient.
*
* ====================================================================
*/
#pragma once
#include <map>
#include <string>
#include <vector>
#include <memory>
namespace ebpf {
namespace cc {
using std::string;
using std::vector;
using std::map;
using std::pair;
using std::unique_ptr;
class StateDeclStmtNode;
class TimerDeclStmtNode;
class VariableDeclStmtNode;
class TableDeclStmtNode;
class StructDeclStmtNode;
template <typename T>
class Scope {
public:
Scope() {}
Scope(Scope<T>* scope, int id) : parent_(scope), id_(id) {}
enum search_type { LOCAL, GLOBAL };
T* lookup(const string& name, bool search_local = true) {
auto it = elems_.find(name);
if (it != elems_.end()) {
return it->second;
}
if (search_local || !parent_) {
return NULL;
}
return parent_->lookup(name, search_local);
}
void add(const string& name, T* n) {
elems_[name] = n;
elems_ordered_.push_back(n);
}
typename map<string, T*>::iterator begin() { return elems_.begin(); }
typename map<string, T*>::iterator end() { return elems_.end(); }
typename vector<T*>::iterator obegin() { return elems_ordered_.begin(); }
typename vector<T*>::iterator oend() { return elems_ordered_.end(); }
Scope<T> *parent_;
int id_;
map<string, T*> elems_;
vector<T*> 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<Scopes> Ptr;
typedef Scope<StructDeclStmtNode> StructScope;
typedef Scope<StateDeclStmtNode> StateScope;
typedef Scope<TimerDeclStmtNode> TimerScope;
typedef Scope<VariableDeclStmtNode> VarScope;
typedef Scope<TableDeclStmtNode> TableScope;
Scopes() : var_id__(0), state_id_(0), var_id_(0),
current_var_scope_(NULL), top_var_scope_(NULL),
current_state_scope_(NULL), top_state_scope_(NULL),
top_timer_scope_(new TimerScope(NULL, 1)),
top_struct_scope_(new StructScope(NULL, 1)),
top_table_scope_(new TableScope(NULL, 1)) {}
~Scopes() {
delete top_timer_scope_;
delete top_struct_scope_;
delete top_table_scope_;
delete top_state_scope_;
}
/// 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() { return current_var_scope_; }
VarScope* top_var() { return top_var_scope_; }
void set_current(StateScope* s) { current_state_scope_ = s; }
StateScope* current_state() { return current_state_scope_; }
StateScope* top_state() { return top_state_scope_; }
TimerScope* top_timer() { return top_timer_scope_; }
StructScope* top_struct() { return top_struct_scope_; }
TableScope* top_table() { return top_table_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_;
TimerScope* top_timer_scope_;
StructScope* top_struct_scope_;
TableScope* top_table_scope_;
};
} // namespace cc
} // namespace ebpf