Add type_aliases() BIF for introspecting type-names of types/values

This commit is contained in:
Jon Siwek 2020-11-06 17:18:44 -08:00
parent 1dda387ac9
commit 77514f234f
3 changed files with 175 additions and 0 deletions

View file

@ -1853,6 +1853,99 @@ function type_name%(t: any%): string
return zeek::make_intrusive<zeek::StringVal>(s);
%}
%%{
static std::map<std::string, std::set<std::string>> build_complete_alias_map()
{
std::map<std::string, std::set<std::string>> rval;
for ( const auto& [name, alias_types] : zeek::Type::GetAliasMap() )
{
rval[name].emplace(name);
for ( const auto& alias_type : alias_types )
{
const auto& alias_name = alias_type->GetName();
rval[name].emplace(alias_name);
rval[alias_name].emplace(name);
}
}
for ( const auto& [name, aliases] : rval )
{
std::map<std::string, bool> more;
for ( const auto& alias_name : aliases )
if ( alias_name != name )
more.emplace(alias_name, false);
for ( ; ; )
{
auto prev_size = more.size();
for ( auto& [alias_name, checked] : more )
{
if ( checked ) continue;
for ( const auto& alias_alias : rval[alias_name] )
more.emplace(alias_alias, false);
checked = true;
}
if ( prev_size == more.size() )
break;
}
for ( const auto& [alias_name, checked] : more )
rval[name].emplace(alias_name);
}
return rval;
}
%%}
## Returns all type name aliases of a value or type.
##
## x: An arbitrary value or type.
##
## Returns: The set of all type name aliases of *x* (or the type of *x*
## if it's a value instead of a type). For primitive values
## and types like :zeek:type:`string` or :zeek:type:`count`,
## this returns an empty set. For types with user-defined
## names like :zeek:type:`record` or :zeek:type:`enum`, the
## returned set contains the original user-defined name for the
## type along with all aliases. For other compound types, like
## :zeek:type:`table`, the returned set is empty unless
## explicitly requesting aliases for a user-defined type alias
## or a value that was explicitly created using a type alias
## (as opposed to originating from an "anonymous" constructor
## or initializer for that compound type).
function type_aliases%(x: any%): string_set
%{
auto rval = make_intrusive<zeek::TableVal>(zeek::id::string_set);
auto t = x->GetType();
if ( t->Tag() == TYPE_TYPE )
t = t->AsTypeType()->GetType();
const auto& tname = t->GetName();
if ( tname.empty() )
return rval;
static auto all_aliases = build_complete_alias_map();
auto it = all_aliases.find(tname);
if ( it == all_aliases.end() )
return rval;
for ( const auto& name : it->second )
rval->Assign(make_intrusive<zeek::StringVal>(name), nullptr);
return rval;
%}
## Returns: list of command-line arguments (``argv``) used to run Zeek.
function zeek_args%(%): string_vec
%{

View file

@ -0,0 +1,22 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
type aliases for 'RED enum val': ColorAlias Color
type aliases for 'Color enum type': ColorAlias Color
type aliases for 'MyRec val': MyRec MyRecAlias
type aliases for 'MyRecAlias val': MyRec MyRecAlias
type aliases for 'MyRec type': MyRec MyRecAlias
type aliases for 'MyRecalias type': MyRec MyRecAlias
type aliases for 'MyString val': it's just a 'string'
type aliases for 'MyString type': MyString AnotherString
type aliases for 'MyOtherString type': MyOtherString
type aliases for 'AnotherString type': MyString AnotherString
type aliases for 'string literal value': it's just a 'string'
type aliases for 'count literal value': it's just a 'count'
type aliases for 'MyTable value': MyTable2 MyTable3 MyTable MyTable4
type aliases for 'MyTable2 value': MyTable2 MyTable3 MyTable MyTable4
type aliases for 'MyTable3 value': MyTable2 MyTable3 MyTable MyTable4
type aliases for 'MyTable4 value': MyTable2 MyTable3 MyTable MyTable4
type aliases for 'MyTable type': MyTable2 MyTable3 MyTable MyTable4
type aliases for 'MyTable2 type': MyTable2 MyTable3 MyTable MyTable4
type aliases for 'MyTable3 type': MyTable2 MyTable3 MyTable MyTable4
type aliases for 'MyTable4 type': MyTable2 MyTable3 MyTable MyTable4
type aliases for 'table value': it's just a 'table[count] of string'

View file

@ -0,0 +1,60 @@
# @TEST-EXEC: zeek -b %INPUT >out
# @TEST-EXEC: btest-diff out
type MyRec: record {
a: bool &optional;
};
type Color: enum { RED, GREEN, BLUE };
type ColorAlias: Color;
type MyRecAlias: MyRec;
type MyString: string;
type MyOtherString: string;
type AnotherString: MyString;
type MyTable: table[count] of string;
type MyTable2: MyTable;
type MyTable3: MyTable2;
type MyTable4: MyTable3;
function type_alias_list(label: string, x: any): string
{
local rval = fmt("type aliases for '%s':", label);
local aliases = type_aliases(x);
if ( |aliases| == 0 )
rval += fmt(" it's just a '%s'", type_name(x));
else
for ( a in aliases )
rval += fmt(" %s", a);
return rval;
}
print type_alias_list("RED enum val", RED);
print type_alias_list("Color enum type", Color);
print type_alias_list("MyRec val", MyRec());
print type_alias_list("MyRecAlias val", MyRecAlias());
print type_alias_list("MyRec type", MyRec);
print type_alias_list("MyRecalias type", MyRecAlias);
local mys: MyString = "hi";
print type_alias_list("MyString val", mys);
print type_alias_list("MyString type", MyString);
print type_alias_list("MyOtherString type", MyOtherString);
print type_alias_list("AnotherString type", AnotherString);
print type_alias_list("string literal value", "test");
print type_alias_list("count literal value", 7);
print type_alias_list("MyTable value", MyTable([1] = "one", [2] = "two"));
print type_alias_list("MyTable2 value", MyTable2([1] = "one", [2] = "two"));
print type_alias_list("MyTable3 value", MyTable3([1] = "one", [2] = "two"));
print type_alias_list("MyTable4 value", MyTable4([1] = "one", [2] = "two"));
print type_alias_list("MyTable type", MyTable);
print type_alias_list("MyTable2 type", MyTable2);
print type_alias_list("MyTable3 type", MyTable3);
print type_alias_list("MyTable4 type", MyTable4);
print type_alias_list("table value", table([1] = "one", [2] = "two"));