From 63f902daff256da03a31338ec45b7bd75c90b00b Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Fri, 11 Mar 2022 14:24:04 -0800 Subject: [PATCH] switch variable initialization over to being expression-based --- src/Var.cc | 157 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 101 insertions(+), 56 deletions(-) diff --git a/src/Var.cc b/src/Var.cc index ce1027b77e..dba0e620fb 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -23,18 +23,6 @@ namespace zeek::detail { -static ValPtr init_val(ExprPtr init, TypePtr t, ValPtr aggr) - { - try - { - return init->InitVal(t, std::move(aggr)); - } - catch ( InterpreterException& e ) - { - return nullptr; - } - } - static bool add_prototype(const IDPtr& id, Type* t, std::vector* attrs, const ExprPtr& init) { @@ -129,9 +117,103 @@ static bool add_prototype(const IDPtr& id, Type* t, std::vector* attrs, return true; } +static void initialize_var(const IDPtr& id, InitClass c, ExprPtr init) + { + if ( ! id->HasVal() ) + { + if ( c == INIT_REMOVE ) + return; + + bool no_init = ! init; + + if ( ! no_init && init->Tag() == EXPR_LIST ) + no_init = init->AsListExpr()->Exprs().empty(); + + if ( no_init ) + { + auto& t = id->GetType(); + + if ( ! IsAggr(t) ) + return; + + ValPtr init_val; + + if ( t->Tag() == TYPE_RECORD ) + { + try + { + init_val = make_intrusive(cast_intrusive(t)); + } + catch ( InterpreterException& ) + { + id->Error("initialization failed"); + return; + } + } + + else if ( t->Tag() == TYPE_TABLE ) + init_val = make_intrusive(cast_intrusive(t), id->GetAttrs()); + + else if ( t->Tag() == TYPE_VECTOR ) + init_val = make_intrusive(cast_intrusive(t)); + + id->SetVal(init_val); + return; + } + + if ( c == INIT_EXTRA ) + c = INIT_FULL; + } + + bool is_const = id->IsConst() || id->IsOption(); + auto lhs = make_intrusive(id, is_const); + ExprPtr assignment; + + if ( c == INIT_FULL ) + assignment = make_intrusive(lhs, init, false); + else if ( c == INIT_EXTRA ) + assignment = make_intrusive(lhs, init); + else if ( c == INIT_REMOVE ) + assignment = make_intrusive(lhs, init); + else + reporter->InternalError("bad InitClass in initialize_var"); + + if ( assignment->IsError() ) + return; + + try + { + (void)assignment->Eval(nullptr); + } + catch ( InterpreterException& ) + { + id->Error("initialization failed"); + } + } + static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init, std::unique_ptr> attr, DeclType dt, bool do_init) { + if ( c == INIT_NONE && init ) + { + // This can happen because the grammar allows any "init_class", + // including none, to be followed by an expression. + init->Warn("initialization not preceded by =/+=/-= is deprecated"); + + // The historical instances of these, such as the + // language/redef-same-prefixtable-idx.zeek btest, treat + // this as += rather than =, and with the initializer + // implicitly inside a list. + init = make_intrusive(init); + c = INIT_EXTRA; + } + + if ( init && init->Tag() == EXPR_LIST ) + { + auto& init_t = t ? t : id->GetType(); + init = expand_op(cast_intrusive(init), init_t); + } + if ( id->GetType() ) { if ( id->IsRedefinable() || (! init && attr && ! IsFunc(id->GetType()->Tag())) ) @@ -166,7 +248,7 @@ static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init, if ( id->GetType() && id->GetType()->Tag() != TYPE_ERROR ) { - if ( dt != VAR_REDEF && (! init || ! do_init || (! t && ! (t = init_type(init.get())))) ) + if ( dt != VAR_REDEF && (! init || ! do_init || (! t && ! (t = init_type(init)))) ) { id->Error("already defined", init.get()); return; @@ -205,7 +287,7 @@ static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init, return; } - t = init_type(init.get()); + t = init_type(init); if ( ! t ) { id->SetType(error_type()); @@ -228,6 +310,8 @@ static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init, auto* ctor = static_cast(init.get()); if ( ctor->GetAttrs() ) id->AddAttrs(ctor->GetAttrs()); + else + ctor->SetAttrs(id->GetAttrs()); } break; @@ -236,6 +320,8 @@ static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init, auto* ctor = static_cast(init.get()); if ( ctor->GetAttrs() ) id->AddAttrs(ctor->GetAttrs()); + else + ctor->SetAttrs(id->GetAttrs()); } break; @@ -258,48 +344,7 @@ static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init, id->SetVal(init, c); else if ( dt != VAR_REDEF || init || ! attr ) - { - ValPtr aggr; - - if ( t->Tag() == TYPE_RECORD ) - { - try - { - aggr = make_intrusive(cast_intrusive(t)); - } - catch ( InterpreterException& ) - { - id->Error("initialization failed"); - return; - } - - if ( init && t ) - // Have an initialization and type is not deduced. - init = make_intrusive( - std::move(init), IntrusivePtr{NewRef{}, t->AsRecordType()}); - } - - else if ( t->Tag() == TYPE_TABLE ) - aggr = make_intrusive(cast_intrusive(t), id->GetAttrs()); - - else if ( t->Tag() == TYPE_VECTOR ) - aggr = make_intrusive(cast_intrusive(t)); - - ValPtr v; - - if ( init ) - { - v = init_val(init, t, aggr); - - if ( ! v ) - return; - } - - if ( aggr ) - id->SetVal(std::move(aggr), c); - else if ( v ) - id->SetVal(std::move(v), c); - } + initialize_var(id, c, init); } if ( dt == VAR_CONST )