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]) + ">";
|
my_name = "lambda_<" + std::to_string(h[0]) + ">";
|
||||||
auto fullname = make_full_var_name(current_module.data(), my_name.data());
|
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 )
|
if ( id )
|
||||||
// Just try again to make a unique lambda name.
|
// 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,
|
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, "::");
|
bool explicit_global = zeek::util::starts_with(name, "::");
|
||||||
|
|
||||||
static std::string global_prefix = util::fmt("%s::", GLOBAL_MODULE_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;
|
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);
|
scopes.push_back(top_scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pop_local_scope() {
|
||||||
|
scopes.pop_back();
|
||||||
|
top_scope = scopes.empty() ? nullptr : scopes.back();
|
||||||
|
}
|
||||||
|
|
||||||
ScopePtr pop_scope() {
|
ScopePtr pop_scope() {
|
||||||
if ( scopes.empty() )
|
if ( scopes.empty() )
|
||||||
reporter->InternalError("scope underflow");
|
reporter->InternalError("scope underflow");
|
||||||
|
|
||||||
|
while ( scopes.back()->GetID() == nullptr )
|
||||||
|
scopes.pop_back();
|
||||||
|
|
||||||
|
auto old_top = scopes.back();
|
||||||
|
|
||||||
scopes.pop_back();
|
scopes.pop_back();
|
||||||
|
|
||||||
auto old_top = top_scope;
|
top_scope = scopes.back();
|
||||||
|
|
||||||
top_scope = scopes.empty() ? nullptr : scopes.back();
|
|
||||||
|
|
||||||
return old_top;
|
return old_top;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopePtr current_scope() { return top_scope; }
|
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(); }
|
ScopePtr global_scope() { return scopes.empty() ? 0 : scopes.front(); }
|
||||||
|
|
||||||
} // namespace zeek::detail
|
} // namespace zeek::detail
|
||||||
|
|
|
@ -81,7 +81,7 @@ protected:
|
||||||
|
|
||||||
// If no_global is true, don't search in the default "global" namespace.
|
// 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,
|
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);
|
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.
|
// Returns the one popped off.
|
||||||
extern ScopePtr pop_scope();
|
extern ScopePtr pop_scope();
|
||||||
|
|
||||||
|
extern void pop_local_scope();
|
||||||
|
|
||||||
extern ScopePtr current_scope();
|
extern ScopePtr current_scope();
|
||||||
|
extern ScopePtr current_function_scope();
|
||||||
extern ScopePtr global_scope();
|
extern ScopePtr global_scope();
|
||||||
|
|
||||||
// Current module (identified by its name).
|
// 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)) {
|
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");
|
Error("return statement outside of function/event");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1419,6 +1419,7 @@ void ReturnStmt::StmtDescribe(ODesc* d) const {
|
||||||
StmtList::StmtList() : Stmt(STMT_LIST) {}
|
StmtList::StmtList() : Stmt(STMT_LIST) {}
|
||||||
|
|
||||||
ValPtr StmtList::Exec(Frame* f, StmtFlowType& flow) {
|
ValPtr StmtList::Exec(Frame* f, StmtFlowType& flow) {
|
||||||
|
push_scope(nullptr, nullptr);
|
||||||
RegisterAccess();
|
RegisterAccess();
|
||||||
flow = FLOW_NEXT;
|
flow = FLOW_NEXT;
|
||||||
|
|
||||||
|
@ -1439,6 +1440,7 @@ ValPtr StmtList::Exec(Frame* f, StmtFlowType& flow) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pop_local_scope();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1729,7 +1731,7 @@ WhenInfo::WhenInfo(ExprPtr arg_cond, FuncType::CaptureList* arg_cl, bool arg_is_
|
||||||
|
|
||||||
lambda_ft->SetCaptures(*cl);
|
lambda_ft->SetCaptures(*cl);
|
||||||
|
|
||||||
auto id = current_scope()->GenerateTemporary("when-internal");
|
auto id = current_function_scope()->GenerateTemporary("when-internal");
|
||||||
id->SetType(lambda_ft);
|
id->SetType(lambda_ft);
|
||||||
push_scope(std::move(id), nullptr);
|
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 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());
|
auto outer_ids = gather_outer_ids(pop_scope(), ingredients->Body());
|
||||||
|
|
||||||
lambda = make_intrusive<LambdaExpr>(std::move(ingredients), std::move(outer_ids), "", ws);
|
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) )
|
if ( ! check_params(i, prototype, args, canon_args, module_name) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if ( Attr* depr_attr = find_attr(current_scope()->Attrs().get(), ATTR_DEPRECATED) )
|
if ( Attr* depr_attr = find_attr(current_function_scope()->Attrs().get(), ATTR_DEPRECATED) )
|
||||||
current_scope()->GetID()->MakeDeprecated(depr_attr->GetExpr());
|
current_function_scope()->GetID()->MakeDeprecated(depr_attr->GetExpr());
|
||||||
|
|
||||||
// Reset the AST node statistics to track afresh for this function.
|
// Reset the AST node statistics to track afresh for this function.
|
||||||
Stmt::ResetNumStmts();
|
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;
|
std::vector<int> saved_in_init;
|
||||||
static int expr_list_has_opt_comma = 0;
|
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 Location func_hdr_location;
|
||||||
static int func_hdr_cond_epoch = 0;
|
static int func_hdr_cond_epoch = 0;
|
||||||
EnumType* cur_enum_type = nullptr;
|
EnumType* cur_enum_type = nullptr;
|
||||||
|
@ -772,8 +769,6 @@ expr:
|
||||||
| TOK_WHEN_LOCAL local_id '=' rhs
|
| TOK_WHEN_LOCAL local_id '=' rhs
|
||||||
{
|
{
|
||||||
set_location(@2, @4);
|
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},
|
$$ = add_and_assign_local({AdoptRef{}, $2}, {AdoptRef{}, $4},
|
||||||
val_mgr->True()).release();
|
val_mgr->True()).release();
|
||||||
}
|
}
|
||||||
|
@ -1012,9 +1007,6 @@ expr:
|
||||||
}
|
}
|
||||||
else
|
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));
|
$$ = new NameExpr(std::move(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1545,9 +1537,6 @@ func_body:
|
||||||
{
|
{
|
||||||
saved_in_init.push_back(in_init);
|
saved_in_init.push_back(in_init);
|
||||||
in_init = 0;
|
in_init = 0;
|
||||||
|
|
||||||
locals_at_this_scope.clear();
|
|
||||||
out_of_scope_locals.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt_list
|
stmt_list
|
||||||
|
@ -1832,19 +1821,18 @@ attr:
|
||||||
stmt:
|
stmt:
|
||||||
'{'
|
'{'
|
||||||
{
|
{
|
||||||
|
push_scope(nullptr, nullptr);
|
||||||
std::set<const ID*> id_set;
|
std::set<const ID*> id_set;
|
||||||
locals_at_this_scope.emplace_back(id_set);
|
|
||||||
}
|
}
|
||||||
opt_no_test_block stmt_list '}'
|
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);
|
set_location(@1, @5);
|
||||||
$$ = $4;
|
$$ = $4;
|
||||||
if ( $3 )
|
if ( $3 )
|
||||||
script_coverage_mgr.DecIgnoreDepth();
|
script_coverage_mgr.DecIgnoreDepth();
|
||||||
|
|
||||||
|
pop_local_scope();
|
||||||
}
|
}
|
||||||
|
|
||||||
| TOK_ASSERT expr opt_assert_msg ';'
|
| 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
|
| TOK_LOCAL local_id opt_type init_class opt_init opt_attr ';' opt_no_test
|
||||||
{
|
{
|
||||||
set_location(@1, @7);
|
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();
|
$$ = build_local($2, $3, $4, $5, $6, VAR_REGULAR, ! $8).release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2174,7 +2160,7 @@ local_id:
|
||||||
TOK_ID
|
TOK_ID
|
||||||
{
|
{
|
||||||
set_location(@1);
|
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();
|
$$ = id.release();
|
||||||
|
|
||||||
if ( $$ )
|
if ( $$ )
|
||||||
|
|
|
@ -406,7 +406,7 @@ static void terminate_zeek() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// free the global scope
|
// free the global scope
|
||||||
pop_scope();
|
pop_local_scope();
|
||||||
|
|
||||||
reporter = nullptr;
|
reporter = nullptr;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue