Migrate TypeList to store IntrusivePtrs

This changes return types of TypeList::Types() and
IndexType::IndexTypes() to return std::vector instead of type_list*
This commit is contained in:
Jon Siwek 2020-05-06 23:12:47 -07:00
parent 011866a908
commit 455fc29b1a
14 changed files with 271 additions and 248 deletions

3
NEWS
View file

@ -86,6 +86,9 @@ Changed Functionality
- The DCE/RPC operation string of "NetrLogonSamLogonWithFlags" has been
corrected from "NetrLogonSameLogonWithFlags".
- ``TypeList::Types()`` and ``IndexType::IndexTypes()`` now return an
``std::vector`` instead of ``type_list*``
Removed Functionality
---------------------

View file

@ -464,20 +464,21 @@ void Attributes::CheckAttr(Attr* a)
if (the_table->IsUnspecifiedTable())
break;
const type_list* func_index_types = e_ft->ArgTypes()->Types();
const auto& func_index_types = e_ft->ArgTypes()->Types();
// Keep backwards compatibility with idx: any idiom.
if ( func_index_types->length() == 2 )
if ( func_index_types.size() == 2 )
{
if ((*func_index_types)[1]->Tag() == TYPE_ANY)
if (func_index_types[1]->Tag() == TYPE_ANY)
break;
}
const type_list* table_index_types = the_table->IndexTypes();
const auto& table_index_types = the_table->IndexTypes();
type_list expected_args;
type_list expected_args(1 + static_cast<int>(table_index_types.size()));
expected_args.push_back(type->AsTableType());
for (const auto& t : *table_index_types)
expected_args.push_back(t);
for ( const auto& t : table_index_types )
expected_args.push_back(t.get());
if ( ! e_ft->CheckArgs(&expected_args) )
Error("&expire_func argument type clash");
@ -510,30 +511,30 @@ void Attributes::CheckAttr(Attr* a)
if ( the_table->IsUnspecifiedTable() )
break;
const type_list* args = c_ft->ArgTypes()->Types();
const type_list* t_indexes = the_table->IndexTypes();
if ( args->length() != ( type->IsSet() ? 2 : 3 ) + t_indexes->length() )
const auto& args = c_ft->ArgTypes()->Types();
const auto& t_indexes = the_table->IndexTypes();
if ( args.size() != ( type->IsSet() ? 2 : 3 ) + t_indexes.size() )
{
Error("&on_change function has incorrect number of arguments");
break;
}
if ( ! same_type((*args)[0], the_table->AsTableType()) )
if ( ! same_type(args[0].get(), the_table->AsTableType()) )
{
Error("&on_change: first argument must be of same type as table");
break;
}
// can't check exact type here yet - the data structures don't exist yet.
if ( (*args)[1]->Tag() != TYPE_ENUM )
if ( args[1]->Tag() != TYPE_ENUM )
{
Error("&on_change: second argument must be a TableChange enum");
break;
}
for ( int i = 0; i < t_indexes->length(); i++ )
for ( size_t i = 0; i < t_indexes.size(); i++ )
{
if ( ! same_type((*args)[2+i], (*t_indexes)[i]) )
if ( ! same_type(args[2+i].get(), t_indexes[i].get()) )
{
Error("&on_change: index types do not match table");
break;
@ -541,7 +542,7 @@ void Attributes::CheckAttr(Attr* a)
}
if ( ! type->IsSet() )
if ( ! same_type((*args)[2+t_indexes->length()], the_table->YieldType()) )
if ( ! same_type(args[2+t_indexes.size()].get(), the_table->YieldType()) )
{
Error("&on_change: value type does not match table");
break;

View file

@ -21,9 +21,9 @@ CompositeHash::CompositeHash(IntrusivePtr<TypeList> composite_type)
// If the only element is a record, don't treat it as a
// singleton, since it needs to be evaluated specially.
if ( type->Types()->length() == 1 )
if ( type->Types().size() == 1 )
{
if ( (*type->Types())[0]->Tag() == TYPE_RECORD )
if ( type->Types()[0]->Tag() == TYPE_RECORD )
{
is_complex_type = true;
is_singleton = false;
@ -45,7 +45,7 @@ CompositeHash::CompositeHash(IntrusivePtr<TypeList> composite_type)
{
// Don't do any further key computations - we'll do them
// via the singleton later.
singleton_tag = (*type->Types())[0]->InternalType();
singleton_tag = type->Types()[0]->InternalType();
size = 0;
key = nullptr;
}
@ -366,20 +366,20 @@ HashKey* CompositeHash::ComputeHash(const Val* v, bool type_check) const
type_check = false; // no need to type-check again.
}
const type_list* tl = type->Types();
const auto& tl = type->Types();
if ( type_check && v->Type()->Tag() != TYPE_LIST )
return nullptr;
auto lv = v->AsListVal();
if ( type_check && lv->Length() != tl->length() )
if ( type_check && lv->Length() != static_cast<int>(tl.size()) )
return nullptr;
char* kp = k;
loop_over_list(*tl, i)
for ( auto i = 0u; i < tl.size(); ++i )
{
kp = SingleValHash(type_check, kp, (*tl)[i], lv->Idx(i).get(), false);
kp = SingleValHash(type_check, kp, tl[i].get(), lv->Idx(i).get(), false);
if ( ! kp )
return nullptr;
}
@ -624,7 +624,7 @@ int CompositeHash::SingleTypeKeySize(BroType* bt, const Val* v,
int CompositeHash::ComputeKeySize(const Val* v, bool type_check, bool calc_static_size) const
{
const type_list* tl = type->Types();
const auto& tl = type->Types();
if ( v )
{
@ -633,14 +633,14 @@ int CompositeHash::ComputeKeySize(const Val* v, bool type_check, bool calc_stati
auto lv = v->AsListVal();
if ( type_check && lv->Length() != tl->length() )
if ( type_check && lv->Length() != static_cast<int>(tl.size()) )
return 0;
}
int sz = 0;
loop_over_list(*tl, i)
for ( auto i = 0u; i < tl.size(); ++i )
{
sz = SingleTypeKeySize((*tl)[i], v ? v->AsListVal()->Idx(i).get() : nullptr,
sz = SingleTypeKeySize(tl[i].get(), v ? v->AsListVal()->Idx(i).get() : nullptr,
type_check, sz, false, calc_static_size);
if ( ! sz )
return 0;
@ -711,14 +711,14 @@ int CompositeHash::SizeAlign(int offset, unsigned int size) const
IntrusivePtr<ListVal> CompositeHash::RecoverVals(const HashKey* k) const
{
auto l = make_intrusive<ListVal>(TYPE_ANY);
const type_list* tl = type->Types();
const auto& tl = type->Types();
const char* kp = (const char*) k->Key();
const char* const k_end = kp + k->Size();
for ( const auto& type : *tl )
for ( const auto& type : tl )
{
IntrusivePtr<Val> v;
kp = RecoverOneVal(k, kp, k_end, type, &v, false);
kp = RecoverOneVal(k, kp, k_end, type.get(), &v, false);
ASSERT(v);
l->Append(std::move(v));
}
@ -1008,7 +1008,7 @@ const char* CompositeHash::RecoverOneVal(const HashKey* k, const char* kp0,
for ( int i = 0; i < n; ++i )
{
IntrusivePtr<Val> v;
BroType* it = (*tl->Types())[i];
BroType* it = tl->Types()[i].get();
kp1 = RecoverOneVal(k, kp1, k_end, it, &v, false);
lv->Append(std::move(v));
}

View file

@ -3103,7 +3103,7 @@ TableConstructorExpr::TableConstructorExpr(IntrusivePtr<ListExpr> constructor_li
attrs = arg_attrs ? new Attributes(arg_attrs, type, false, false) : nullptr;
type_list* indices = type->AsTableType()->Indices()->Types();
const auto& indices = type->AsTableType()->Indices()->Types();
const expr_list& cle = op->AsListExpr()->Exprs();
// check and promote all index expressions in ctor list
@ -3119,14 +3119,14 @@ TableConstructorExpr::TableConstructorExpr(IntrusivePtr<ListExpr> constructor_li
expr_list& idx_exprs = idx_expr->AsListExpr()->Exprs();
if ( idx_exprs.length() != indices->length() )
if ( idx_exprs.length() != static_cast<int>(indices.size()) )
continue;
loop_over_list(idx_exprs, j)
{
Expr* idx = idx_exprs[j];
auto promoted_idx = check_and_promote_expr(idx, (*indices)[j]);
auto promoted_idx = check_and_promote_expr(idx, indices[j].get());
if ( promoted_idx )
{
@ -3221,17 +3221,17 @@ SetConstructorExpr::SetConstructorExpr(IntrusivePtr<ListExpr> constructor_list,
attrs = arg_attrs ? new Attributes(arg_attrs, type, false, false) : nullptr;
type_list* indices = type->AsTableType()->Indices()->Types();
const auto& indices = type->AsTableType()->Indices()->Types();
expr_list& cle = op->AsListExpr()->Exprs();
if ( indices->length() == 1 )
if ( indices.size() == 1 )
{
if ( ! check_and_promote_exprs_to_type(op->AsListExpr(),
(*indices)[0]) )
indices[0].get()) )
ExprError("inconsistent type in set constructor");
}
else if ( indices->length() > 1 )
else if ( indices.size() > 1 )
{
// Check/promote each expression in composite index.
loop_over_list(cle, i)
@ -4555,9 +4555,9 @@ IntrusivePtr<Val> ListExpr::InitVal(const BroType* t, IntrusivePtr<Val> aggr) co
if ( ! aggr && type->AsTypeList()->AllMatch(t, true) )
{
auto v = make_intrusive<ListVal>(TYPE_ANY);
const type_list* tl = type->AsTypeList()->Types();
const auto& tl = type->AsTypeList()->Types();
if ( exprs.length() != tl->length() )
if ( exprs.length() != static_cast<int>(tl.size()) )
{
Error("index mismatch", t);
return nullptr;
@ -4565,7 +4565,7 @@ IntrusivePtr<Val> ListExpr::InitVal(const BroType* t, IntrusivePtr<Val> aggr) co
loop_over_list(exprs, i)
{
auto vi = exprs[i]->InitVal((*tl)[i], nullptr);
auto vi = exprs[i]->InitVal(tl[i].get(), nullptr);
if ( ! vi )
return nullptr;
@ -4583,9 +4583,9 @@ IntrusivePtr<Val> ListExpr::InitVal(const BroType* t, IntrusivePtr<Val> aggr) co
return nullptr;
}
const type_list* tl = t->AsTypeList()->Types();
const auto& tl = t->AsTypeList()->Types();
if ( exprs.length() != tl->length() )
if ( exprs.length() != static_cast<int>(tl.size()) )
{
Error("index mismatch", t);
return nullptr;
@ -4595,7 +4595,7 @@ IntrusivePtr<Val> ListExpr::InitVal(const BroType* t, IntrusivePtr<Val> aggr) co
loop_over_list(exprs, i)
{
auto vi = exprs[i]->InitVal((*tl)[i], nullptr);
auto vi = exprs[i]->InitVal(tl[i].get(), nullptr);
if ( ! vi )
return nullptr;
@ -4703,7 +4703,7 @@ IntrusivePtr<Val> ListExpr::AddSetInit(const BroType* t, IntrusivePtr<Val> aggr)
else if ( expr->Type()->Tag() == TYPE_LIST )
element = expr->InitVal(it, nullptr);
else
element = expr->InitVal((*it->Types())[0], nullptr);
element = expr->InitVal(it->Types()[0].get(), nullptr);
if ( ! element )
return nullptr;
@ -4725,7 +4725,7 @@ IntrusivePtr<Val> ListExpr::AddSetInit(const BroType* t, IntrusivePtr<Val> aggr)
if ( expr->Type()->Tag() == TYPE_LIST )
element = check_and_promote(std::move(element), it, true);
else
element = check_and_promote(std::move(element), (*it->Types())[0], true);
element = check_and_promote(std::move(element), it->Types()[0].get(), true);
if ( ! element )
return nullptr;
@ -5013,12 +5013,12 @@ IntrusivePtr<Expr> check_and_promote_expr(Expr* const e, BroType* t)
bool check_and_promote_exprs(ListExpr* const elements, TypeList* types)
{
expr_list& el = elements->Exprs();
const type_list* tl = types->Types();
const auto& tl = types->Types();
if ( tl->length() == 1 && (*tl)[0]->Tag() == TYPE_ANY )
if ( tl.size() == 1 && tl[0]->Tag() == TYPE_ANY )
return true;
if ( el.length() != tl->length() )
if ( el.length() != static_cast<int>(tl.size()) )
{
types->Error("indexing mismatch", elements);
return false;
@ -5027,11 +5027,11 @@ bool check_and_promote_exprs(ListExpr* const elements, TypeList* types)
loop_over_list(el, i)
{
Expr* e = el[i];
auto promoted_e = check_and_promote_expr(e, (*tl)[i]);
auto promoted_e = check_and_promote_expr(e, tl[i].get());
if ( ! promoted_e )
{
e->Error("type mismatch", (*tl)[i]);
e->Error("type mismatch", tl[i].get());
return false;
}

View file

@ -1069,27 +1069,28 @@ ForStmt::ForStmt(id_list* arg_loop_vars, IntrusivePtr<Expr> loop_expr)
if ( e->Type()->Tag() == TYPE_TABLE )
{
const type_list* indices = e->Type()->AsTableType()->IndexTypes();
if ( indices->length() != loop_vars->length() )
const auto& indices = e->Type()->AsTableType()->IndexTypes();
if ( static_cast<int>(indices.size()) != loop_vars->length() )
{
e->Error("wrong index size");
return;
}
for ( int i = 0; i < indices->length(); i++ )
for ( auto i = 0u; i < indices.size(); i++ )
{
BroType* ind_type = (*indices)[i]->Ref();
const auto& ind_type = indices[i];
if ( (*loop_vars)[i]->Type() )
{
if ( ! same_type((*loop_vars)[i]->Type(), ind_type) )
(*loop_vars)[i]->Type()->Error("type clash in iteration", ind_type);
if ( ! same_type((*loop_vars)[i]->Type(), ind_type.get()) )
(*loop_vars)[i]->Type()->Error("type clash in iteration",
ind_type.get());
}
else
{
add_local({NewRef{}, (*loop_vars)[i]},
{NewRef{}, ind_type}, INIT_NONE,
add_local({NewRef{}, (*loop_vars)[i]}, ind_type, INIT_NONE,
nullptr, nullptr, VAR_REGULAR);
}
}

View file

@ -153,16 +153,10 @@ unsigned int BroType::MemoryAllocation() const
return padded_sizeof(*this);
}
TypeList::~TypeList()
{
for ( const auto& type : types )
Unref(type);
}
bool TypeList::AllMatch(const BroType* t, bool is_init) const
{
for ( const auto& type : types )
if ( ! same_type(type, t, is_init) )
if ( ! same_type(type.get(), t, is_init) )
return false;
return true;
}
@ -172,7 +166,7 @@ void TypeList::Append(IntrusivePtr<BroType> t)
if ( pure_type && ! same_type(t.get(), pure_type.get()) )
reporter->InternalError("pure type-list violation");
types.push_back(t.release());
types.emplace_back(std::move(t));
}
void TypeList::AppendEvenIfNotPure(IntrusivePtr<BroType> t)
@ -180,7 +174,7 @@ void TypeList::AppendEvenIfNotPure(IntrusivePtr<BroType> t)
if ( pure_type && ! same_type(t.get(), pure_type.get()) )
pure_type = nullptr;
types.push_back(t.release());
types.emplace_back(std::move(t));
}
void TypeList::Describe(ODesc* d) const
@ -193,14 +187,14 @@ void TypeList::Describe(ODesc* d) const
d->Add(IsPure());
if ( IsPure() )
pure_type->Describe(d);
d->Add(types.length());
d->Add(static_cast<uint64_t>(types.size()));
}
if ( IsPure() )
pure_type->Describe(d);
else
{
loop_over_list(types, i)
for ( size_t i = 0; i < types.size(); ++i )
{
if ( i > 0 && ! d->IsBinary() )
d->Add(",");
@ -212,9 +206,16 @@ void TypeList::Describe(ODesc* d) const
unsigned int TypeList::MemoryAllocation() const
{
unsigned int size = 0;
for ( const auto& t : types )
size += t->MemoryAllocation();
size += pad_size(types.capacity() * sizeof(decltype(types)::value_type));
return BroType::MemoryAllocation()
+ padded_sizeof(*this) - padded_sizeof(BroType)
+ types.MemoryAllocation() - padded_sizeof(types);
+ size;
}
IndexType::~IndexType() = default;
@ -222,10 +223,10 @@ IndexType::~IndexType() = default;
int IndexType::MatchesIndex(ListExpr* const index) const
{
// If we have a type indexed by subnets, addresses are ok.
const type_list* types = indices->Types();
const auto& types = indices->Types();
const expr_list& exprs = index->Exprs();
if ( types->length() == 1 && (*types)[0]->Tag() == TYPE_SUBNET &&
if ( types.size() == 1 && types[0]->Tag() == TYPE_SUBNET &&
exprs.length() == 1 && exprs[0]->Type()->Tag() == TYPE_ADDR )
return MATCHES_INDEX_SCALAR;
@ -248,11 +249,14 @@ void IndexType::Describe(ODesc* d) const
BroType::Describe(d);
if ( ! d->IsBinary() )
d->Add("[");
loop_over_list(*IndexTypes(), i)
const auto& its = IndexTypes();
for ( auto i = 0u; i < its.size(); ++i )
{
if ( ! d->IsBinary() && i > 0 )
d->Add(",");
(*IndexTypes())[i]->Describe(d);
its[i]->Describe(d);
}
if ( ! d->IsBinary() )
d->Add("]");
@ -277,12 +281,14 @@ void IndexType::DescribeReST(ODesc* d, bool roles_only) const
d->Add("` ");
d->Add("[");
loop_over_list(*IndexTypes(), i)
const auto& its = IndexTypes();
for ( auto i = 0u; i < its.size(); ++i )
{
if ( i > 0 )
d->Add(", ");
const BroType* t = (*IndexTypes())[i];
const auto& t = its[i];
if ( ! t->GetName().empty() )
{
@ -313,8 +319,8 @@ void IndexType::DescribeReST(ODesc* d, bool roles_only) const
bool IndexType::IsSubNetIndex() const
{
const type_list* types = indices->Types();
if ( types->length() == 1 && (*types)[0]->Tag() == TYPE_SUBNET )
const auto& types = indices->Types();
if ( types.size() == 1 && types[0]->Tag() == TYPE_SUBNET )
return true;
return false;
}
@ -325,9 +331,9 @@ TableType::TableType(IntrusivePtr<TypeList> ind, IntrusivePtr<BroType> yield)
if ( ! indices )
return;
type_list* tl = indices->Types();
const auto& tl = indices->Types();
for ( const auto& tli : *tl )
for ( const auto& tli : tl )
{
InternalTypeTag t = tli->InternalType();
@ -354,7 +360,7 @@ IntrusivePtr<BroType> TableType::ShallowClone()
bool TableType::IsUnspecifiedTable() const
{
// Unspecified types have an empty list of indices.
return indices->Types()->length() == 0;
return indices->Types().empty();
}
SetType::SetType(IntrusivePtr<TypeList> ind, IntrusivePtr<ListExpr> arg_elements)
@ -370,27 +376,27 @@ SetType::SetType(IntrusivePtr<TypeList> ind, IntrusivePtr<ListExpr> arg_elements
else
{
TypeList* tl_type = elements->Type()->AsTypeList();
type_list* tl = tl_type->Types();
const auto& tl = tl_type->Types();
if ( tl->length() < 1 )
if ( tl.size() < 1 )
{
Error("no type given for set");
SetError();
}
else if ( tl->length() == 1 )
else if ( tl.size() == 1 )
{
IntrusivePtr<BroType> ft{NewRef{}, flatten_type((*tl)[0])};
IntrusivePtr<BroType> ft{NewRef{}, flatten_type(tl[0].get())};
indices = make_intrusive<TypeList>(ft);
indices->Append(std::move(ft));
}
else
{
auto t = merge_types((*tl)[0], (*tl)[1]);
auto t = merge_types(tl[0].get(), tl[1].get());
for ( int i = 2; t && i < tl->length(); ++i )
t = merge_types(t.get(), (*tl)[i]);
for ( size_t i = 2; t && i < tl.size(); ++i )
t = merge_types(t.get(), tl[i].get());
if ( ! t )
{
@ -493,22 +499,34 @@ int FuncType::MatchesIndex(ListExpr* const index) const
bool FuncType::CheckArgs(const type_list* args, bool is_init) const
{
const type_list* my_args = arg_types->Types();
std::vector<IntrusivePtr<BroType>> as;
as.reserve(args->length());
if ( my_args->length() != args->length() )
for ( auto a : *args )
as.emplace_back(NewRef{}, a);
return CheckArgs(as, is_init);
}
bool FuncType::CheckArgs(const std::vector<IntrusivePtr<BroType>>& args,
bool is_init) const
{
Warn(fmt("Wrong number of arguments for function. Expected %d, got %d.",
args->length(), my_args->length()));
const auto& my_args = arg_types->Types();
if ( my_args.size() != args.size() )
{
Warn(fmt("Wrong number of arguments for function. Expected %zu, got %zu.",
args.size(), my_args.size()));
return false;
}
bool success = true;
for ( int i = 0; i < my_args->length(); ++i )
if ( ! same_type((*args)[i], (*my_args)[i], is_init) )
for ( size_t i = 0; i < my_args.size(); ++i )
if ( ! same_type(args[i].get(), my_args[i].get(), is_init) )
{
Warn(fmt("Type mismatch in function argument #%d. Expected %s, got %s.",
i, type_name((*args)[i]->Tag()), type_name((*my_args)[i]->Tag())));
Warn(fmt("Type mismatch in function argument #%zu. Expected %s, got %s.",
i, type_name(args[i]->Tag()), type_name(my_args[i]->Tag())));
success = false;
}
@ -785,12 +803,14 @@ static string container_type_name(const BroType* ft)
s = "set[";
else
s = "table[";
const type_list* tl = ((const IndexType*) ft)->IndexTypes();
loop_over_list(*tl, i)
const auto& tl = ((const IndexType*) ft)->IndexTypes();
for ( auto i = 0u; i < tl.size(); ++i )
{
if ( i > 0 )
s += ",";
s += container_type_name((*tl)[i]);
s += container_type_name(tl[i].get());
}
s += "]";
if ( ft->YieldType() )
@ -1576,14 +1596,14 @@ bool same_type(const BroType* t1, const BroType* t2, bool is_init, bool match_re
case TYPE_LIST:
{
const type_list* tl1 = t1->AsTypeList()->Types();
const type_list* tl2 = t2->AsTypeList()->Types();
const auto& tl1 = t1->AsTypeList()->Types();
const auto& tl2 = t2->AsTypeList()->Types();
if ( tl1->length() != tl2->length() )
if ( tl1.size() != tl2.size() )
return false;
loop_over_list(*tl1, i)
if ( ! same_type((*tl1)[i], (*tl2)[i], is_init, match_record_field_names) )
for ( auto i = 0u; i < tl1.size(); ++i )
if ( ! same_type(tl1[i].get(), tl2[i].get(), is_init, match_record_field_names) )
return false;
return true;
@ -1666,14 +1686,15 @@ const BroType* flatten_type(const BroType* t)
if ( tl->IsPure() )
return tl->GetPureType().get();
const type_list* types = tl->Types();
const auto& types = tl->Types();
if ( types->length() == 0 )
if ( types.size() == 0 )
reporter->InternalError("empty type list in flatten_type");
const BroType* ft = (*types)[0];
if ( types->length() == 1 || tl->AllMatch(ft, false) )
return ft;
const auto& ft = types[0];
if ( types.size() == 1 || tl->AllMatch(ft, false) )
return ft.get();
return t;
}
@ -1821,13 +1842,11 @@ IntrusivePtr<BroType> merge_types(const BroType* t1, const BroType* t2)
const IndexType* it1 = (const IndexType*) t1;
const IndexType* it2 = (const IndexType*) t2;
const type_list* tl1 = it1->IndexTypes();
const type_list* tl2 = it2->IndexTypes();
const auto& tl1 = it1->IndexTypes();
const auto& tl2 = it2->IndexTypes();
IntrusivePtr<TypeList> tl3;
if ( tl1 || tl2 )
{
if ( ! tl1 || ! tl2 || tl1->length() != tl2->length() )
if ( tl1.size() != tl2.size() )
{
t1->Error("incompatible types", t2);
return nullptr;
@ -1835,15 +1854,14 @@ IntrusivePtr<BroType> merge_types(const BroType* t1, const BroType* t2)
tl3 = make_intrusive<TypeList>();
loop_over_list(*tl1, i)
for ( auto i = 0u; i < tl1.size(); ++i )
{
auto tl3_i = merge_types((*tl1)[i], (*tl2)[i]);
auto tl3_i = merge_types(tl1[i].get(), tl2[i].get());
if ( ! tl3_i )
return nullptr;
tl3->Append(std::move(tl3_i));
}
}
const BroType* y1 = t1->YieldType();
const BroType* y2 = t2->YieldType();
@ -1926,12 +1944,12 @@ IntrusivePtr<BroType> merge_types(const BroType* t1, const BroType* t2)
return nullptr;
}
const type_list* l1 = tl1->Types();
const type_list* l2 = tl2->Types();
const auto& l1 = tl1->Types();
const auto& l2 = tl2->Types();
if ( l1->length() == 0 || l2->length() == 0 )
if ( l1.size() == 0 || l2.size() == 0 )
{
if ( l1->length() == 0 )
if ( l1.size() == 0 )
tl1->Error("empty list");
else
tl2->Error("empty list");
@ -1944,20 +1962,21 @@ IntrusivePtr<BroType> merge_types(const BroType* t1, const BroType* t2)
// the initialization expression into a set of values.
// So the merge type of the list is the type of one
// of the elements, providing they're consistent.
return merge_types((*l1)[0], (*l2)[0]);
return merge_types(l1[0].get(), l2[0].get());
}
// Impure lists - must have the same size and match element
// by element.
if ( l1->length() != l2->length() )
if ( l1.size() != l2.size() )
{
tl1->Error("different number of indices", tl2);
return nullptr;
}
auto tl3 = make_intrusive<TypeList>();
loop_over_list(*l1, i)
tl3->Append(merge_types((*l1)[i], (*l2)[i]));
for ( auto i = 0u; i < l1.size(); ++i )
tl3->Append(merge_types(l1[i].get(), l2[i].get()));
return tl3;
}
@ -1993,21 +2012,21 @@ IntrusivePtr<BroType> merge_types(const BroType* t1, const BroType* t2)
IntrusivePtr<BroType> merge_type_list(ListExpr* elements)
{
TypeList* tl_type = elements->Type()->AsTypeList();
type_list* tl = tl_type->Types();
const auto& tl = tl_type->Types();
if ( tl->length() < 1 )
if ( tl.size() < 1 )
{
reporter->Error("no type can be inferred for empty list");
return nullptr;
}
IntrusivePtr<BroType> t{NewRef{}, (*tl)[0]};
auto t = tl[0];
if ( tl->length() == 1 )
if ( tl.size() == 1 )
return t;
for ( int i = 1; t && i < tl->length(); ++i )
t = merge_types(t.get(), (*tl)[i]);
for ( size_t i = 1; t && i < tl.size(); ++i )
t = merge_types(t.get(), tl[i].get());
if ( ! t )
reporter->Error("inconsistent types in list");
@ -2024,8 +2043,8 @@ static BroType* reduce_type(BroType* t)
else if ( t->IsSet() )
{
TypeList* tl = t->AsTableType()->Indices();
if ( tl->Types()->length() == 1 )
return (*tl->Types())[0];
if ( tl->Types().size() == 1 )
return tl->Types()[0].get();
else
return tl;
}
@ -2044,7 +2063,7 @@ IntrusivePtr<BroType> init_type(Expr* init)
return nullptr;
if ( t->Tag() == TYPE_LIST &&
t->AsTypeList()->Types()->length() != 1 )
t->AsTypeList()->Types().size() != 1 )
{
init->Error("list used in scalar initialization");
return nullptr;

View file

@ -353,10 +353,8 @@ public:
{
}
~TypeList() override;
const type_list* Types() const { return &types; }
type_list* Types() { return &types; }
const std::vector<IntrusivePtr<BroType>>& Types() const
{ return types; }
bool IsPure() const { return pure_type != nullptr; }
@ -386,7 +384,7 @@ public:
protected:
IntrusivePtr<BroType> pure_type;
type_list types;
std::vector<IntrusivePtr<BroType>> types;
};
class IndexType : public BroType {
@ -394,7 +392,10 @@ public:
int MatchesIndex(ListExpr* index) const override;
TypeList* Indices() const { return indices.get(); }
const type_list* IndexTypes() const { return indices->Types(); }
const std::vector<IntrusivePtr<BroType>>& IndexTypes() const
{ return indices->Types(); }
BroType* YieldType() override;
const BroType* YieldType() const override;
@ -478,6 +479,8 @@ public:
int MatchesIndex(ListExpr* index) const override;
bool CheckArgs(const type_list* args, bool is_init = false) const;
bool CheckArgs(const std::vector<IntrusivePtr<BroType>>& args,
bool is_init = false) const;
TypeList* ArgTypes() const { return arg_types.get(); }

View file

@ -266,7 +266,7 @@ IntrusivePtr<Val> Val::SizeVal() const
case TYPE_INTERNAL_OTHER:
if ( type->Tag() == TYPE_FUNC )
return val_mgr->Count(val.func_val->FType()->ArgTypes()->Types()->length());
return val_mgr->Count(val.func_val->FType()->ArgTypes()->Types().size());
if ( type->Tag() == TYPE_FILE )
return make_intrusive<Val>(val.file_val->Size(), TYPE_DOUBLE);
@ -1353,8 +1353,8 @@ static void find_nested_record_types(BroType* t, std::set<RecordType*>* found)
return;
case TYPE_LIST:
{
for ( auto& type : *t->AsTypeList()->Types() )
find_nested_record_types(type, found);
for ( const auto& type : t->AsTypeList()->Types() )
find_nested_record_types(type.get(), found);
}
return;
case TYPE_FUNC:
@ -1380,12 +1380,12 @@ TableVal::TableVal(IntrusivePtr<TableType> t, IntrusivePtr<Attributes> a) : Val(
if ( ! is_parsing )
return;
for ( const auto& t : *table_type->IndexTypes() )
for ( const auto& t : table_type->IndexTypes() )
{
std::set<RecordType*> found;
// TODO: this likely doesn't have to be repeated for each new TableVal,
// can remember the resulting dependencies per TableType
find_nested_record_types(t, &found);
find_nested_record_types(t.get(), &found);
for ( auto rt : found )
parse_time_table_record_dependencies[rt].emplace_back(NewRef{}, this);
@ -1766,7 +1766,7 @@ bool TableVal::ExpandAndInit(IntrusivePtr<Val> index, IntrusivePtr<Val> new_val)
ListVal* iv = index->AsListVal();
if ( iv->BaseTag() != TYPE_ANY )
{
if ( table_type->Indices()->Types()->length() != 1 )
if ( table_type->Indices()->Types().size() != 1 )
reporter->InternalError("bad singleton list index");
for ( int i = 0; i < iv->Length(); ++i )
@ -2146,14 +2146,14 @@ ListVal* TableVal::ConvertToList(TypeTag t) const
IntrusivePtr<ListVal> TableVal::ToPureListVal() const
{
type_list* tl = table_type->Indices()->Types();
if ( tl->length() != 1 )
const auto& tl = table_type->Indices()->Types();
if ( tl.size() != 1 )
{
InternalWarning("bad index type in TableVal::ToPureListVal");
return nullptr;
}
return ToListVal((*tl)[0]->Tag());
return ToListVal(tl[0]->Tag());
}
ListVal* TableVal::ConvertToPureList() const
@ -2481,10 +2481,9 @@ double TableVal::CallExpireFunc(IntrusivePtr<ListVal> idx)
const Func* f = vf->AsFunc();
zeek::Args vl;
const auto func_args = f->FType()->ArgTypes()->Types();
const auto& func_args = f->FType()->ArgTypes()->Types();
// backwards compatibility with idx: any idiom
bool any_idiom = func_args->length() == 2 && func_args->back()->Tag() == TYPE_ANY;
bool any_idiom = func_args.size() == 2 && func_args.back()->Tag() == TYPE_ANY;
if ( ! any_idiom )
{

View file

@ -212,17 +212,17 @@ struct val_converter {
for ( auto& item : a )
{
auto expected_index_types = tt->Indices()->Types();
const auto& expected_index_types = tt->Indices()->Types();
broker::vector composite_key;
auto indices = caf::get_if<broker::vector>(&item);
if ( indices )
{
if ( expected_index_types->length() == 1 )
if ( expected_index_types.size() == 1 )
{
auto index_is_vector_or_record =
(*expected_index_types)[0]->Tag() == TYPE_RECORD ||
(*expected_index_types)[0]->Tag() == TYPE_VECTOR;
expected_index_types[0]->Tag() == TYPE_RECORD ||
expected_index_types[0]->Tag() == TYPE_VECTOR;
if ( index_is_vector_or_record )
{
@ -238,8 +238,7 @@ struct val_converter {
indices = &composite_key;
}
if ( static_cast<size_t>(expected_index_types->length()) !=
indices->size() )
if ( expected_index_types.size() != indices->size() )
return nullptr;
auto list_val = make_intrusive<ListVal>(TYPE_ANY);
@ -247,7 +246,7 @@ struct val_converter {
for ( auto i = 0u; i < indices->size(); ++i )
{
auto index_val = bro_broker::data_to_val(move((*indices)[i]),
(*expected_index_types)[i]);
expected_index_types[i].get());
if ( ! index_val )
return nullptr;
@ -272,17 +271,17 @@ struct val_converter {
for ( auto& item : a )
{
auto expected_index_types = tt->Indices()->Types();
const auto& expected_index_types = tt->Indices()->Types();
broker::vector composite_key;
auto indices = caf::get_if<broker::vector>(&item.first);
if ( indices )
{
if ( expected_index_types->length() == 1 )
if ( expected_index_types.size() == 1 )
{
auto index_is_vector_or_record =
(*expected_index_types)[0]->Tag() == TYPE_RECORD ||
(*expected_index_types)[0]->Tag() == TYPE_VECTOR;
expected_index_types[0]->Tag() == TYPE_RECORD ||
expected_index_types[0]->Tag() == TYPE_VECTOR;
if ( index_is_vector_or_record )
{
@ -298,8 +297,7 @@ struct val_converter {
indices = &composite_key;
}
if ( static_cast<size_t>(expected_index_types->length()) !=
indices->size() )
if ( expected_index_types.size() != indices->size() )
return nullptr;
auto list_val = make_intrusive<ListVal>(TYPE_ANY);
@ -307,7 +305,7 @@ struct val_converter {
for ( auto i = 0u; i < indices->size(); ++i )
{
auto index_val = bro_broker::data_to_val(move((*indices)[i]),
(*expected_index_types)[i]);
expected_index_types[i].get());
if ( ! index_val )
return nullptr;
@ -561,17 +559,17 @@ struct type_checker {
for ( const auto& item : a )
{
auto expected_index_types = tt->Indices()->Types();
const auto& expected_index_types = tt->Indices()->Types();
auto indices = caf::get_if<broker::vector>(&item);
vector<const broker::data*> indices_to_check;
if ( indices )
{
if ( expected_index_types->length() == 1 )
if ( expected_index_types.size() == 1 )
{
auto index_is_vector_or_record =
(*expected_index_types)[0]->Tag() == TYPE_RECORD ||
(*expected_index_types)[0]->Tag() == TYPE_VECTOR;
expected_index_types[0]->Tag() == TYPE_RECORD ||
expected_index_types[0]->Tag() == TYPE_VECTOR;
if ( index_is_vector_or_record )
// Disambiguate from composite key w/ multiple vals.
@ -595,13 +593,12 @@ struct type_checker {
else
indices_to_check.emplace_back(&item);
if ( static_cast<size_t>(expected_index_types->length()) !=
indices_to_check.size() )
if ( expected_index_types.size() != indices_to_check.size() )
return false;
for ( auto i = 0u; i < indices_to_check.size(); ++i )
{
auto expect = (*expected_index_types)[i];
auto expect = expected_index_types[i].get();
auto& index_to_check = *(indices_to_check)[i];
if ( ! data_type_check(index_to_check, expect) )
@ -621,17 +618,17 @@ struct type_checker {
for ( auto& item : a )
{
auto expected_index_types = tt->Indices()->Types();
const auto& expected_index_types = tt->Indices()->Types();
auto indices = caf::get_if<broker::vector>(&item.first);
vector<const broker::data*> indices_to_check;
if ( indices )
{
if ( expected_index_types->length() == 1 )
if ( expected_index_types.size() == 1 )
{
auto index_is_vector_or_record =
(*expected_index_types)[0]->Tag() == TYPE_RECORD ||
(*expected_index_types)[0]->Tag() == TYPE_VECTOR;
expected_index_types[0]->Tag() == TYPE_RECORD ||
expected_index_types[0]->Tag() == TYPE_VECTOR;
if ( index_is_vector_or_record )
// Disambiguate from composite key w/ multiple vals.
@ -656,15 +653,14 @@ struct type_checker {
indices_to_check.emplace_back(&item.first);
if ( static_cast<size_t>(expected_index_types->length()) !=
indices_to_check.size() )
if ( expected_index_types.size() != indices_to_check.size() )
{
return false;
}
for ( auto i = 0u; i < indices_to_check.size(); ++i )
{
auto expect = (*expected_index_types)[i];
auto expect = expected_index_types[i].get();
auto& index_to_check = *(indices_to_check)[i];
if ( ! data_type_check(index_to_check, expect) )

View file

@ -742,9 +742,9 @@ RecordVal* Manager::MakeEvent(val_list* args, Frame* frame)
}
auto got_type = (*args)[i]->Type();
auto expected_type = (*func->FType()->ArgTypes()->Types())[i - 1];
const auto& expected_type = func->FType()->ArgTypes()->Types()[i - 1];
if ( ! same_type(got_type, expected_type) )
if ( ! same_type(got_type, expected_type.get()) )
{
rval->Assign(0, nullptr);
Error("event parameter #%d type mismatch, got %s, expect %s", i,
@ -978,13 +978,13 @@ void Manager::ProcessEvent(const broker::topic& topic, broker::zeek::Event ev)
return;
}
auto arg_types = handler->FType(false)->ArgTypes()->Types();
const auto& arg_types = handler->FType(false)->ArgTypes()->Types();
if ( static_cast<size_t>(arg_types->length()) != args.size() )
if ( arg_types.size() != args.size() )
{
reporter->Warning("got event message '%s' with invalid # of args,"
" got %zd, expected %d", name.data(), args.size(),
arg_types->length());
" got %zd, expected %zu", name.data(), args.size(),
arg_types.size());
return;
}
@ -994,8 +994,8 @@ void Manager::ProcessEvent(const broker::topic& topic, broker::zeek::Event ev)
for ( auto i = 0u; i < args.size(); ++i )
{
auto got_type = args[i].get_type_name();
auto expected_type = (*arg_types)[i];
auto val = data_to_val(std::move(args[i]), expected_type);
const auto& expected_type = arg_types[i];
auto val = data_to_val(std::move(args[i]), expected_type.get());
if ( val )
vl.emplace_back(std::move(val));

View file

@ -12,12 +12,12 @@ static bool is_string_set(const BroType* type)
if ( ! type->IsSet() )
return false;
auto index_types = type->AsSetType()->IndexTypes();
const auto& index_types = type->AsSetType()->IndexTypes();
if ( index_types->length() != 1 )
if ( index_types.size() != 1 )
return false;
return (*index_types)[0]->Tag() == TYPE_STRING;
return index_types[0]->Tag() == TYPE_STRING;
}
std::set<std::string> val_to_topic_set(Val* val)

View file

@ -336,21 +336,21 @@ bool Manager::CreateEventStream(RecordVal* fval)
return false;
}
const type_list* args = etype->ArgTypes()->Types();
const auto& args = etype->ArgTypes()->Types();
if ( args->length() < 2 )
if ( args.size() < 2 )
{
reporter->Error("Input stream %s: Event does not take enough arguments", stream_name.c_str());
return false;
}
if ( ! same_type((*args)[1], BifType::Enum::Input::Event, false) )
if ( ! same_type(args[1].get(), BifType::Enum::Input::Event, false) )
{
reporter->Error("Input stream %s: Event's second attribute must be of type Input::Event", stream_name.c_str());
return false;
}
if ( ! same_type((*args)[0], BifType::Record::Input::EventDescription, false) )
if ( ! same_type(args[0].get(), BifType::Record::Input::EventDescription, false) )
{
reporter->Error("Input stream %s: Event's first attribute must be of type Input::EventDescription", stream_name.c_str());
return false;
@ -358,7 +358,7 @@ bool Manager::CreateEventStream(RecordVal* fval)
if ( want_record->InternalInt() == 0 )
{
if ( args->length() != fields->NumFields() + 2 )
if ( static_cast<int>(args.size()) != fields->NumFields() + 2 )
{
reporter->Error("Input stream %s: Event has wrong number of arguments", stream_name.c_str());
return false;
@ -366,17 +366,17 @@ bool Manager::CreateEventStream(RecordVal* fval)
for ( int i = 0; i < fields->NumFields(); i++ )
{
if ( ! same_type((*args)[i + 2], fields->FieldType(i) ) )
if ( ! same_type(args[i + 2].get(), fields->FieldType(i) ) )
{
ODesc desc1;
ODesc desc2;
(*args)[i + 2]->Describe(&desc1);
args[i + 2]->Describe(&desc1);
fields->FieldType(i)->Describe(&desc2);
reporter->Error("Input stream %s: Incompatible type for event in field %d. Need type '%s':%s, got '%s':%s",
stream_name.c_str(), i + 3,
type_name(fields->FieldType(i)->Tag()), desc2.Description(),
type_name((*args)[i + 2]->Tag()), desc1.Description());
type_name(args[i + 2]->Tag()), desc1.Description());
return false;
}
@ -386,21 +386,21 @@ bool Manager::CreateEventStream(RecordVal* fval)
else if ( want_record->InternalInt() == 1 )
{
if ( args->length() != 3 )
if ( args.size() != 3 )
{
reporter->Error("Input stream %s: Event has wrong number of arguments", stream_name.c_str());
return false;
}
if ( ! same_type((*args)[2], fields ) )
if ( ! same_type(args[2].get(), fields ) )
{
ODesc desc1;
ODesc desc2;
(*args)[2]->Describe(&desc1);
args[2]->Describe(&desc1);
fields->Describe(&desc2);
reporter->Error("Input stream %s: Incompatible type '%s':%s for event, which needs type '%s':%s\n",
stream_name.c_str(),
type_name((*args)[2]->Tag()), desc1.Description(),
type_name(args[2]->Tag()), desc1.Description(),
type_name(fields->Tag()), desc2.Description());
return false;
}
@ -486,9 +486,10 @@ bool Manager::CreateTableStream(RecordVal* fval)
// check if index fields match table description
int num = idx->NumFields();
const type_list* tl = dst->Type()->AsTableType()->IndexTypes();
const auto& tl = dst->Type()->AsTableType()->IndexTypes();
int j;
loop_over_list(*tl, j)
for ( j = 0; j < static_cast<int>(tl.size()); ++j )
{
if ( j >= num )
{
@ -496,16 +497,16 @@ bool Manager::CreateTableStream(RecordVal* fval)
return false;
}
if ( ! same_type(idx->FieldType(j), (*tl)[j]) )
if ( ! same_type(idx->FieldType(j), tl[j].get()) )
{
ODesc desc1;
ODesc desc2;
idx->FieldType(j)->Describe(&desc1);
(*tl)[j]->Describe(&desc2);
tl[j]->Describe(&desc2);
reporter->Error("Input stream %s: Table type does not match index type. Need type '%s':%s, got '%s':%s", stream_name.c_str(),
type_name(idx->FieldType(j)->Tag()), desc1.Description(),
type_name((*tl)[j]->Tag()), desc2.Description());
type_name(tl[j]->Tag()), desc2.Description());
return false;
}
@ -563,54 +564,54 @@ bool Manager::CreateTableStream(RecordVal* fval)
return false;
}
const type_list* args = etype->ArgTypes()->Types();
const auto& args = etype->ArgTypes()->Types();
if ( args->length() != 4 )
if ( args.size() != 4 )
{
reporter->Error("Input stream %s: Table event must take 4 arguments", stream_name.c_str());
return false;
}
if ( ! same_type((*args)[0], BifType::Record::Input::TableDescription, false) )
if ( ! same_type(args[0].get(), BifType::Record::Input::TableDescription, false) )
{
reporter->Error("Input stream %s: Table event's first attribute must be of type Input::TableDescription", stream_name.c_str());
return false;
}
if ( ! same_type((*args)[1], BifType::Enum::Input::Event, false) )
if ( ! same_type(args[1].get(), BifType::Enum::Input::Event, false) )
{
reporter->Error("Input stream %s: Table event's second attribute must be of type Input::Event", stream_name.c_str());
return false;
}
if ( ! same_type((*args)[2], idx) )
if ( ! same_type(args[2].get(), idx) )
{
ODesc desc1;
ODesc desc2;
idx->Describe(&desc1);
(*args)[2]->Describe(&desc2);
args[2]->Describe(&desc2);
reporter->Error("Input stream %s: Table event's index attributes do not match. Need '%s', got '%s'", stream_name.c_str(),
desc1.Description(), desc2.Description());
return false;
}
if ( want_record->InternalInt() == 1 && val && ! same_type((*args)[3], val.get()) )
if ( want_record->InternalInt() == 1 && val && ! same_type(args[3].get(), val.get()) )
{
ODesc desc1;
ODesc desc2;
val->Describe(&desc1);
(*args)[3]->Describe(&desc2);
args[3]->Describe(&desc2);
reporter->Error("Input stream %s: Table event's value attributes do not match. Need '%s', got '%s'", stream_name.c_str(),
desc1.Description(), desc2.Description());
return false;
}
else if ( want_record->InternalInt() == 0
&& val && !same_type((*args)[3], val->FieldType(0) ) )
&& val && !same_type(args[3].get(), val->FieldType(0) ) )
{
ODesc desc1;
ODesc desc2;
val->FieldType(0)->Describe(&desc1);
(*args)[3]->Describe(&desc2);
args[3]->Describe(&desc2);
reporter->Error("Input stream %s: Table event's value attribute does not match. Need '%s', got '%s'", stream_name.c_str(),
desc1.Description(), desc2.Description());
return false;
@ -710,33 +711,33 @@ bool Manager::CheckErrorEventTypes(const std::string& stream_name, const Func* e
return false;
}
const type_list* args = etype->ArgTypes()->Types();
const auto& args = etype->ArgTypes()->Types();
if ( args->length() != 3 )
if ( args.size() != 3 )
{
reporter->Error("Input stream %s: Error event must take 3 arguments", stream_name.c_str());
return false;
}
if ( table && ! same_type((*args)[0], BifType::Record::Input::TableDescription, false) )
if ( table && ! same_type(args[0].get(), BifType::Record::Input::TableDescription, false) )
{
reporter->Error("Input stream %s: Error event's first attribute must be of type Input::TableDescription", stream_name.c_str());
return false;
}
if ( ! table && ! same_type((*args)[0], BifType::Record::Input::EventDescription, false) )
if ( ! table && ! same_type(args[0].get(), BifType::Record::Input::EventDescription, false) )
{
reporter->Error("Input stream %s: Error event's first attribute must be of type Input::EventDescription", stream_name.c_str());
return false;
}
if ( (*args)[1]->Tag() != TYPE_STRING )
if ( args[1]->Tag() != TYPE_STRING )
{
reporter->Error("Input stream %s: Error event's second attribute must be of type string", stream_name.c_str());
return false;
}
if ( ! same_type((*args)[2], BifType::Enum::Reporter::Level, false) )
if ( ! same_type(args[2].get(), BifType::Enum::Reporter::Level, false) )
{
reporter->Error("Input stream %s: Error event's third attribute must be of type Reporter::Level", stream_name.c_str());
return false;

View file

@ -278,15 +278,15 @@ bool Manager::CreateStream(EnumVal* id, RecordVal* sval)
return false;
}
const type_list* args = etype->ArgTypes()->Types();
const auto& args = etype->ArgTypes()->Types();
if ( args->length() != 1 )
if ( args.size() != 1 )
{
reporter->Error("stream event must take a single argument");
return false;
}
if ( ! same_type((*args)[0], columns) )
if ( ! same_type(args[0].get(), columns) )
{
reporter->Error("stream event's argument type does not match column record type");
return false;

View file

@ -15,7 +15,7 @@ static bool call_option_handlers_and_set_value(StringVal* name, ID* i,
{
for ( auto handler_function : i->GetOptionHandlers() )
{
bool add_loc = handler_function->FType()->AsFuncType()->ArgTypes()->Types()->length() == 3;
bool add_loc = handler_function->FType()->AsFuncType()->ArgTypes()->Types().size() == 3;
zeek::Args vl;
vl.reserve(2 + add_loc);
vl.emplace_back(NewRef{}, name);
@ -170,32 +170,32 @@ function Option::set_change_handler%(ID: string, on_change: any, priority: int &
return val_mgr->False();
}
const type_list* args = on_change->Type()->AsFuncType()->ArgTypes()->Types();
if ( args->length() < 2 || args->length() > 3 )
const auto& args = on_change->Type()->AsFuncType()->ArgTypes()->Types();
if ( args.size() < 2 || args.size() > 3 )
{
builtin_error(fmt("Wrong number of arguments for passed function in Option::on_change for ID '%s'; expected 2 or 3, got %d",
ID->CheckString(), args->length()));
builtin_error(fmt("Wrong number of arguments for passed function in Option::on_change for ID '%s'; expected 2 or 3, got %zu",
ID->CheckString(), args.size()));
return val_mgr->False();
}
if ( (*args)[0]->Tag() != TYPE_STRING )
if ( args[0]->Tag() != TYPE_STRING )
{
builtin_error(fmt("First argument of passed function has to be string in Option::on_change for ID '%s'; got '%s'",
ID->CheckString(), type_name((*args)[0]->Tag())));
ID->CheckString(), type_name(args[0]->Tag())));
return val_mgr->False();
}
if ( ! same_type((*args)[1], i->Type()) )
if ( ! same_type(args[1].get(), i->Type()) )
{
builtin_error(fmt("Second argument of passed function has to be %s in Option::on_change for ID '%s'; got '%s'",
type_name(i->Type()->Tag()), ID->CheckString(), type_name((*args)[1]->Tag())));
type_name(i->Type()->Tag()), ID->CheckString(), type_name(args[1]->Tag())));
return val_mgr->False();
}
if ( args->length() == 3 && (*args)[2]->Tag() != TYPE_STRING )
if ( args.size() == 3 && args[2]->Tag() != TYPE_STRING )
{
builtin_error(fmt("Third argument of passed function has to be string in Option::on_change for ID '%s'; got '%s'",
ID->CheckString(), type_name((*args)[2]->Tag())));
ID->CheckString(), type_name(args[2]->Tag())));
return val_mgr->False();
}