mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 06:38:20 +00:00
[WIP] Make statement lists have a scope
Note that this doesn't actually properly execute shadowing, it simply makes it not error. And introduces a bunch of other problems. The reason this doesn't shadow variables is that locals are created at parse time (hence why a scope is needed in both `Stmt.cc` and `parse.y` for the statement lists), but locals are used at execution time (obviously). This means that executing the local will just grab the outer scope one every time - the inner scope one goes to die. So the next step *could* be to move locals to getting created at execution time, which seems like it's what should happen. But that may be a lot of work. Optionally, we can alse just add a scope counter and "append" that in some way to the variable's name. That seems pretty easy. Not that shadowing is that important to do anyway, I just wanted to try.
This commit is contained in:
parent
b22ec06568
commit
5d6674f05f
7 changed files with 44 additions and 31 deletions
|
@ -4321,7 +4321,7 @@ void LambdaExpr::BuildName() {
|
|||
|
||||
my_name = "lambda_<" + std::to_string(h[0]) + ">";
|
||||
auto fullname = make_full_var_name(current_module.data(), my_name.data());
|
||||
const auto& id = current_scope()->Find(fullname);
|
||||
const auto& id = current_function_scope()->Find(fullname);
|
||||
|
||||
if ( id )
|
||||
// Just try again to make a unique lambda name.
|
||||
|
|
30
src/Scope.cc
30
src/Scope.cc
|
@ -90,7 +90,7 @@ TraversalCode Scope::Traverse(TraversalCallback* cb) const {
|
|||
}
|
||||
|
||||
const IDPtr& lookup_ID(const char* name, const char* curr_module, bool no_global, bool same_module_only,
|
||||
bool check_export) {
|
||||
bool check_export, bool same_scope_only) {
|
||||
bool explicit_global = zeek::util::starts_with(name, "::");
|
||||
|
||||
static std::string global_prefix = util::fmt("%s::", GLOBAL_MODULE_NAME);
|
||||
|
@ -123,6 +123,9 @@ const IDPtr& lookup_ID(const char* name, const char* curr_module, bool no_global
|
|||
|
||||
return id;
|
||||
}
|
||||
|
||||
if ( same_scope_only )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,20 +173,39 @@ void push_scope(IDPtr id, std::unique_ptr<std::vector<AttrPtr>> attrs) {
|
|||
scopes.push_back(top_scope);
|
||||
}
|
||||
|
||||
void pop_local_scope() {
|
||||
scopes.pop_back();
|
||||
top_scope = scopes.empty() ? nullptr : scopes.back();
|
||||
}
|
||||
|
||||
ScopePtr pop_scope() {
|
||||
if ( scopes.empty() )
|
||||
reporter->InternalError("scope underflow");
|
||||
|
||||
while ( scopes.back()->GetID() == nullptr )
|
||||
scopes.pop_back();
|
||||
|
||||
auto old_top = scopes.back();
|
||||
|
||||
scopes.pop_back();
|
||||
|
||||
auto old_top = top_scope;
|
||||
|
||||
top_scope = scopes.empty() ? nullptr : scopes.back();
|
||||
top_scope = scopes.back();
|
||||
|
||||
return old_top;
|
||||
}
|
||||
|
||||
ScopePtr current_scope() { return top_scope; }
|
||||
|
||||
ScopePtr current_function_scope() {
|
||||
for ( auto s_i = scopes.rbegin(); s_i != scopes.rend(); ++s_i ) {
|
||||
if ( (*s_i)->GetID() != nullptr ) {
|
||||
return *s_i;
|
||||
}
|
||||
}
|
||||
|
||||
return top_scope;
|
||||
}
|
||||
|
||||
ScopePtr global_scope() { return scopes.empty() ? 0 : scopes.front(); }
|
||||
|
||||
} // namespace zeek::detail
|
||||
|
|
|
@ -81,7 +81,7 @@ protected:
|
|||
|
||||
// If no_global is true, don't search in the default "global" namespace.
|
||||
extern const IDPtr& lookup_ID(const char* name, const char* module, bool no_global = false,
|
||||
bool same_module_only = false, bool check_export = true);
|
||||
bool same_module_only = false, bool check_export = true, bool same_scope_only = false);
|
||||
|
||||
extern IDPtr install_ID(const char* name, const char* module_name, bool is_global, bool is_export);
|
||||
|
||||
|
@ -91,7 +91,10 @@ extern void push_existing_scope(ScopePtr scope);
|
|||
// Returns the one popped off.
|
||||
extern ScopePtr pop_scope();
|
||||
|
||||
extern void pop_local_scope();
|
||||
|
||||
extern ScopePtr current_scope();
|
||||
extern ScopePtr current_function_scope();
|
||||
extern ScopePtr global_scope();
|
||||
|
||||
// Current module (identified by its name).
|
||||
|
|
10
src/Stmt.cc
10
src/Stmt.cc
|
@ -1355,9 +1355,9 @@ TraversalCode FallthroughStmt::Traverse(TraversalCallback* cb) const {
|
|||
}
|
||||
|
||||
ReturnStmt::ReturnStmt(ExprPtr arg_e) : ExprStmt(STMT_RETURN, std::move(arg_e)) {
|
||||
auto s = current_scope();
|
||||
auto s = current_function_scope();
|
||||
|
||||
if ( ! s || ! s->GetID() ) {
|
||||
if ( ! s ) {
|
||||
Error("return statement outside of function/event");
|
||||
return;
|
||||
}
|
||||
|
@ -1419,6 +1419,7 @@ void ReturnStmt::StmtDescribe(ODesc* d) const {
|
|||
StmtList::StmtList() : Stmt(STMT_LIST) {}
|
||||
|
||||
ValPtr StmtList::Exec(Frame* f, StmtFlowType& flow) {
|
||||
push_scope(nullptr, nullptr);
|
||||
RegisterAccess();
|
||||
flow = FLOW_NEXT;
|
||||
|
||||
|
@ -1439,6 +1440,7 @@ ValPtr StmtList::Exec(Frame* f, StmtFlowType& flow) {
|
|||
return result;
|
||||
}
|
||||
|
||||
pop_local_scope();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1729,7 +1731,7 @@ WhenInfo::WhenInfo(ExprPtr arg_cond, FuncType::CaptureList* arg_cl, bool arg_is_
|
|||
|
||||
lambda_ft->SetCaptures(*cl);
|
||||
|
||||
auto id = current_scope()->GenerateTemporary("when-internal");
|
||||
auto id = current_function_scope()->GenerateTemporary("when-internal");
|
||||
id->SetType(lambda_ft);
|
||||
push_scope(std::move(id), nullptr);
|
||||
|
||||
|
@ -1848,7 +1850,7 @@ void WhenInfo::Build(StmtPtr ws) {
|
|||
|
||||
auto shebang = make_intrusive<StmtList>(do_test, do_bodies, dummy_return);
|
||||
|
||||
auto ingredients = std::make_shared<FunctionIngredients>(current_scope(), shebang, current_module);
|
||||
auto ingredients = std::make_shared<FunctionIngredients>(current_function_scope(), shebang, current_module);
|
||||
auto outer_ids = gather_outer_ids(pop_scope(), ingredients->Body());
|
||||
|
||||
lambda = make_intrusive<LambdaExpr>(std::move(ingredients), std::move(outer_ids), "", ws);
|
||||
|
|
|
@ -644,8 +644,8 @@ void begin_func(IDPtr id, const char* module_name, FunctionFlavor flavor, bool i
|
|||
if ( ! check_params(i, prototype, args, canon_args, module_name) )
|
||||
break;
|
||||
|
||||
if ( Attr* depr_attr = find_attr(current_scope()->Attrs().get(), ATTR_DEPRECATED) )
|
||||
current_scope()->GetID()->MakeDeprecated(depr_attr->GetExpr());
|
||||
if ( Attr* depr_attr = find_attr(current_function_scope()->Attrs().get(), ATTR_DEPRECATED) )
|
||||
current_function_scope()->GetID()->MakeDeprecated(depr_attr->GetExpr());
|
||||
|
||||
// Reset the AST node statistics to track afresh for this function.
|
||||
Stmt::ResetNumStmts();
|
||||
|
|
22
src/parse.y
22
src/parse.y
|
@ -154,9 +154,6 @@ bool defining_global_ID = false;
|
|||
std::vector<int> saved_in_init;
|
||||
static int expr_list_has_opt_comma = 0;
|
||||
|
||||
std::vector<std::set<const ID*>> locals_at_this_scope;
|
||||
static std::unordered_set<const ID*> out_of_scope_locals;
|
||||
|
||||
static Location func_hdr_location;
|
||||
static int func_hdr_cond_epoch = 0;
|
||||
EnumType* cur_enum_type = nullptr;
|
||||
|
@ -772,8 +769,6 @@ expr:
|
|||
| TOK_WHEN_LOCAL local_id '=' rhs
|
||||
{
|
||||
set_location(@2, @4);
|
||||
if ( ! locals_at_this_scope.empty() )
|
||||
locals_at_this_scope.back().insert($2);
|
||||
$$ = add_and_assign_local({AdoptRef{}, $2}, {AdoptRef{}, $4},
|
||||
val_mgr->True()).release();
|
||||
}
|
||||
|
@ -1012,9 +1007,6 @@ expr:
|
|||
}
|
||||
else
|
||||
{
|
||||
if ( out_of_scope_locals.count(id.get()) > 0 )
|
||||
id->Error("use of out-of-scope local; move declaration to outer scope");
|
||||
|
||||
$$ = new NameExpr(std::move(id));
|
||||
}
|
||||
}
|
||||
|
@ -1545,9 +1537,6 @@ func_body:
|
|||
{
|
||||
saved_in_init.push_back(in_init);
|
||||
in_init = 0;
|
||||
|
||||
locals_at_this_scope.clear();
|
||||
out_of_scope_locals.clear();
|
||||
}
|
||||
|
||||
stmt_list
|
||||
|
@ -1832,19 +1821,18 @@ attr:
|
|||
stmt:
|
||||
'{'
|
||||
{
|
||||
push_scope(nullptr, nullptr);
|
||||
std::set<const ID*> id_set;
|
||||
locals_at_this_scope.emplace_back(id_set);
|
||||
}
|
||||
opt_no_test_block stmt_list '}'
|
||||
{
|
||||
auto& scope_locals = locals_at_this_scope.back();
|
||||
out_of_scope_locals.insert(scope_locals.begin(), scope_locals.end());
|
||||
locals_at_this_scope.pop_back();
|
||||
|
||||
set_location(@1, @5);
|
||||
$$ = $4;
|
||||
if ( $3 )
|
||||
script_coverage_mgr.DecIgnoreDepth();
|
||||
|
||||
pop_local_scope();
|
||||
}
|
||||
|
||||
| TOK_ASSERT expr opt_assert_msg ';'
|
||||
|
@ -1949,8 +1937,6 @@ stmt:
|
|||
| TOK_LOCAL local_id opt_type init_class opt_init opt_attr ';' opt_no_test
|
||||
{
|
||||
set_location(@1, @7);
|
||||
if ( ! locals_at_this_scope.empty() )
|
||||
locals_at_this_scope.back().insert($2);
|
||||
$$ = build_local($2, $3, $4, $5, $6, VAR_REGULAR, ! $8).release();
|
||||
}
|
||||
|
||||
|
@ -2174,7 +2160,7 @@ local_id:
|
|||
TOK_ID
|
||||
{
|
||||
set_location(@1);
|
||||
auto id = lookup_ID($1, current_module.c_str());
|
||||
auto id = lookup_ID($1, current_module.c_str(), false, false, true, true);
|
||||
$$ = id.release();
|
||||
|
||||
if ( $$ )
|
||||
|
|
|
@ -406,7 +406,7 @@ static void terminate_zeek() {
|
|||
#endif
|
||||
|
||||
// free the global scope
|
||||
pop_scope();
|
||||
pop_local_scope();
|
||||
|
||||
reporter = nullptr;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue