"if ( ... ) &analyze" language feature

This commit is contained in:
Vern Paxson 2023-05-19 12:46:01 -07:00
parent 052cda9df0
commit 9f4da24644
6 changed files with 207 additions and 62 deletions

View file

@ -6,6 +6,7 @@
#include <memory>
#include "zeek/ActivationManager.h"
#include "zeek/Desc.h"
#include "zeek/EventRegistry.h"
#include "zeek/Expr.h"
@ -234,7 +235,7 @@ static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init,
{
if ( IsFunc(id->GetType()->Tag()) )
add_prototype(id, t.get(), attr.get(), init);
else
else if ( activation_mgr->IsActivated() )
id->Error("already defined", init.get());
return;
@ -405,7 +406,18 @@ static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init,
void add_global(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init,
std::unique_ptr<std::vector<AttrPtr>> attr, DeclType dt)
{
make_var(id, std::move(t), c, std::move(init), std::move(attr), dt, true);
bool do_init = activation_mgr->IsActivated();
if ( dt == VAR_REDEF )
{
activation_mgr->AddingRedef(id, c, init, attr);
if ( ! do_init )
// Don't actually change the attributes.
attr = nullptr;
}
make_var(id, std::move(t), c, std::move(init), std::move(attr), dt, do_init);
}
StmtPtr add_local(IDPtr id, TypePtr t, InitClass c, ExprPtr init,
@ -711,6 +723,8 @@ void begin_func(IDPtr id, const char* module_name, FunctionFlavor flavor, bool i
else if ( is_redef )
id->Error("redef of not-previously-declared value");
bool is_activated = activation_mgr->IsActivated();
if ( id->HasVal() )
{
FunctionFlavor id_flavor = id->GetVal()->AsFunc()->Flavor();
@ -724,12 +738,17 @@ void begin_func(IDPtr id, const char* module_name, FunctionFlavor flavor, bool i
case FUNC_FLAVOR_EVENT:
case FUNC_FLAVOR_HOOK:
if ( is_redef )
// Clear out value so it will be replaced.
id->SetVal(nullptr);
{
activation_mgr->RedefingHandler(id);
if ( ! is_activated )
// Clear out value so it will be replaced.
id->SetVal(nullptr);
}
break;
case FUNC_FLAVOR_FUNCTION:
if ( ! id->IsRedefinable() )
if ( ! id->IsRedefinable() && is_activated )
id->Error("already defined", t.get());
break;
@ -753,12 +772,15 @@ 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 ( is_activated )
{
if ( Attr* depr_attr = find_attr(current_scope()->Attrs().get(), ATTR_DEPRECATED) )
current_scope()->GetID()->MakeDeprecated(depr_attr->GetExpr());
// Reset the AST node statistics to track afresh for this function.
Stmt::ResetNumStmts();
Expr::ResetNumExprs();
// Reset the AST node statistics to track afresh for this function.
Stmt::ResetNumStmts();
Expr::ResetNumExprs();
}
}
class OuterIDBindingFinder : public TraversalCallback
@ -846,7 +868,7 @@ void end_func(StmtPtr body, const char* module_name, bool free_of_conditionals)
oi->num_stmts = Stmt::GetNumStmts();
oi->num_exprs = Expr::GetNumExprs();
auto ingredients = std::make_unique<FunctionIngredients>(pop_scope(), std::move(body),
auto ingredients = std::make_shared<FunctionIngredients>(pop_scope(), std::move(body),
module_name);
auto id = ingredients->GetID();
if ( ! id->HasVal() )
@ -854,27 +876,27 @@ void end_func(StmtPtr body, const char* module_name, bool free_of_conditionals)
auto f = make_intrusive<ScriptFunc>(id);
id->SetVal(make_intrusive<FuncVal>(std::move(f)));
id->SetConst();
activation_mgr->AddingGlobalVal(id);
}
id->GetVal()->AsFunc()->AddBody(ingredients->Body(), ingredients->Inits(),
ingredients->FrameSize(), ingredients->Priority(),
ingredients->Groups());
script_coverage_mgr.AddFunction(id, ingredients->Body());
auto func_ptr = cast_intrusive<FuncVal>(id->GetVal())->AsFuncPtr();
auto func = cast_intrusive<ScriptFunc>(func_ptr);
func->SetScope(ingredients->Scope());
for ( const auto& group : ingredients->Groups() )
group->AddFunc(func);
activation_mgr->AddingBody(id, ingredients);
analyze_func(std::move(func));
if ( activation_mgr->IsActivated() )
{
func->AddBody(ingredients->Body(), ingredients->Inits(), ingredients->FrameSize(),
ingredients->Priority(), ingredients->Groups());
// Note: ideally, something would take ownership of this memory until the
// end of script execution, but that's essentially the same as the
// lifetime of the process at the moment, so ok to "leak" it.
ingredients.release();
for ( const auto& group : ingredients->Groups() )
group->AddFunc(func);
analyze_func(std::move(func));
}
}
IDPList gather_outer_ids(ScopePtr scope, StmtPtr body)