[Spicy] Clean up representation of EVT record fields.

This commit is contained in:
Robin Sommer 2023-08-21 10:25:49 +02:00
parent cdadd934ce
commit 36a6770e98
No known key found for this signature in database
GPG key ID: 6BEDA4DA6B8B23E3
5 changed files with 41 additions and 18 deletions

View file

@ -9,6 +9,7 @@ public type Val = __library_type("::zeek::ValPtr");
public type BroType = __library_type("::zeek::TypePtr");
public type EventHandlerPtr = __library_type("::zeek::EventHandlerPtr");
public type PortRange = __library_type("::zeek::spicy::rt::PortRange");
public type RecordField = __library_type("::zeek::spicy::rt::RecordField");
declare public PortRange make_port_range(port begin_, port end_) &cxxname="zeek::spicy::rt::make_port_range" &have_prototype;
@ -29,10 +30,10 @@ declare public void raise_event(EventHandlerPtr handler, vector<Val> args) &cxxn
declare public BroType event_arg_type(EventHandlerPtr handler, uint<64> idx) &cxxname="zeek::spicy::rt::event_arg_type" &have_prototype;
declare public Val to_val(any x, BroType target) &cxxname="zeek::spicy::rt::to_val" &have_prototype;
type RecordField = tuple<string, BroType, bool, bool>; # (ID, type, optional, log)
declare public BroType create_base_type(ZeekTypeTag tag) &cxxname="zeek::spicy::rt::create_base_type" &have_prototype;
declare public BroType create_enum_type(string ns, string id, vector<tuple<string, int<64>>> labels) &cxxname="zeek::spicy::rt::create_enum_type" &have_prototype;
declare public BroType create_record_type(string ns, string id, vector<RecordField> fields) &cxxname="zeek::spicy::rt::create_record_type" &have_prototype;
declare public RecordField create_record_field(string id, BroType type_, bool is_optional, bool is_log) &cxxname="zeek::spicy::rt::create_record_field" &have_prototype;
declare public BroType create_table_type(BroType key, optional<BroType> value = Null) &cxxname="zeek::spicy::rt::create_table_type" &have_prototype;
declare public BroType create_vector_type(BroType elem) &cxxname="zeek::spicy::rt::create_vector_type" &have_prototype;

View file

@ -126,25 +126,30 @@ TypePtr rt::create_record_type(const std::string& ns, const std::string& id,
auto decls = std::make_unique<type_decl_list>();
for ( const auto& [id, type, optional, log] : fields ) {
for ( const auto& f : fields ) {
auto attrs = make_intrusive<detail::Attributes>(nullptr, true, false);
if ( optional ) {
if ( f.is_optional ) {
auto optional_ = make_intrusive<detail::Attr>(detail::ATTR_OPTIONAL);
attrs->AddAttr(std::move(optional_));
}
if ( log ) {
if ( f.is_log ) {
auto log_ = make_intrusive<detail::Attr>(detail::ATTR_LOG);
attrs->AddAttr(std::move(log_));
}
decls->append(new TypeDecl(util::copy_string(id.c_str()), type, std::move(attrs)));
decls->append(new TypeDecl(util::copy_string(f.id.c_str()), f.type, std::move(attrs)));
}
return make_intrusive<RecordType>(decls.release());
}
rt::RecordField rt::create_record_field(const std::string& id, const TypePtr& type, hilti::rt::Bool is_optional,
hilti::rt::Bool is_log) {
return rt::RecordField{id, type, is_optional, is_log};
}
TypePtr rt::create_table_type(TypePtr key, std::optional<TypePtr> value) {
auto _ = hilti::rt::profiler::start("zeek/rt/create_table_type");
auto idx = make_intrusive<TypeList>();

View file

@ -151,9 +151,17 @@ extern TypePtr create_enum_type(
const std::string& ns, const std::string& id,
const hilti::rt::Vector<std::tuple<std::string, hilti::rt::integer::safe<int64_t>>>& labels);
using RecordField = std::tuple<std::string, TypePtr, hilti::rt::Bool, hilti::rt::Bool>; // (ID, type, optional, &log)
struct RecordField {
std::string id; /**< name of record field */
TypePtr type; /**< Spicy-side type object */
bool is_optional; /**< true if field is optional */
bool is_log; /**< true if field has `&log` */
};
extern TypePtr create_record_type(const std::string& ns, const std::string& id,
const hilti::rt::Vector<RecordField>& fields);
extern RecordField create_record_field(const std::string& id, const TypePtr& type, hilti::rt::Bool is_optional,
hilti::rt::Bool is_log);
extern TypePtr create_table_type(TypePtr key, std::optional<TypePtr> value);
extern TypePtr create_vector_type(const TypePtr& elem);

View file

@ -1335,6 +1335,12 @@ struct VisitorZeekType : hilti::visitor::PreOrder<hilti::Result<hilti::Expressio
{builder::string(ns), builder::string(local), builder::vector(fields)});
}
hilti::Expression create_record_field(const hilti::ID& id, const hilti::Expression& type, bool optional,
bool log) const {
return builder::call("zeek_rt::create_record_field",
{builder::string(id), type, builder::bool_(optional), builder::bool_(log)});
}
result_t base_type(const char* tag) { return builder::call("zeek_rt::create_base_type", {builder::id(tag)}); }
result_t createZeekType(const hilti::Type& t, const std::optional<hilti::ID>& id_ = {}) {
@ -1419,8 +1425,7 @@ struct VisitorZeekType : hilti::visitor::PreOrder<hilti::Result<hilti::Expressio
if ( ! ztype )
return ztype.error();
fields.emplace_back(builder::tuple(
{builder::string(f.id()), *ztype, builder::bool_(f.isOptional()), builder::bool_(false)}));
fields.emplace_back(create_record_field(f.id(), *ztype, f.isOptional(), false));
}
return create_record_type(id()->namespace_(), id()->local(), fields);
@ -1436,8 +1441,7 @@ struct VisitorZeekType : hilti::visitor::PreOrder<hilti::Result<hilti::Expressio
if ( ! ztype )
return ztype.error();
fields.emplace_back(
builder::tuple({builder::string(*f.id()), *ztype, builder::bool_(false), builder::bool_(false)}));
fields.emplace_back(create_record_field(*f.id(), *ztype, false, false));
}
hilti::ID local;
@ -1466,18 +1470,16 @@ struct VisitorZeekType : hilti::visitor::PreOrder<hilti::Result<hilti::Expressio
std::vector<hilti::Expression> fields;
for ( const auto& f : gc->recordFields(t) ) {
auto field_id = std::get<0>(f);
auto export_ = gc->exportForField(*id(), hilti::ID(field_id));
auto export_ = gc->exportForField(*id(), hilti::ID(f.id));
if ( export_.skip )
continue;
auto ztype = createZeekType(std::get<1>(f));
auto ztype = createZeekType(f.type);
if ( ! ztype )
return ztype.error();
fields.emplace_back(builder::tuple({builder::string(std::get<0>(f)), *ztype, builder::bool_(std::get<2>(f)),
builder::bool_(export_.log)}));
fields.emplace_back(create_record_field(f.id, *ztype, f.is_optional, export_.log));
}
return create_record_type(id()->namespace_(), id()->local(), fields);
@ -1507,11 +1509,13 @@ struct VisitorUnitFields : hilti::visitor::PreOrder<void, VisitorUnitFields> {
if ( f.isTransient() || f.parseType().isA<hilti::type::Void>() )
return;
fields.emplace_back(f.id(), f.itemType(), true);
auto field = GlueCompiler::RecordField{.id = f.id(), .type = f.itemType(), .is_optional = true};
fields.emplace_back(std::move(field));
}
void operator()(const ::spicy::type::unit::item::Variable& f, const position_t p) {
fields.emplace_back(f.id(), f.itemType(), f.isOptional());
auto field = GlueCompiler::RecordField{.id = f.id(), .type = f.itemType(), .is_optional = f.isOptional()};
fields.emplace_back(std::move(field));
}
void operator()(const ::spicy::type::unit::item::Switch& f, const position_t p) {

View file

@ -201,7 +201,12 @@ public:
/** Generates code to convert a HILTI type to a corresponding Zeek type at runtime. */
hilti::Result<hilti::Expression> createZeekType(const hilti::Type& t, const hilti::ID& id) const;
using RecordField = std::tuple<std::string, hilti::Type, bool>; /**< (ID, type, optional) */
/** Return type for `recordField()`. */
struct RecordField {
hilti::ID id; /**< name of record field */
hilti::Type type; /**< Spicy-side type object */
bool is_optional; /**< true if field is optional */
};
/**
* Helper to retrieve a list of Zeek-side record fields that converting a