From 36a6770e9891114b4f42dac3728040c67cc9411e Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Mon, 21 Aug 2023 10:25:49 +0200 Subject: [PATCH] [Spicy] Clean up representation of EVT record fields. --- scripts/spicy/zeek_rt.hlt | 3 ++- src/spicy/runtime-support.cc | 13 +++++++++---- src/spicy/runtime-support.h | 10 +++++++++- src/spicy/spicyz/glue-compiler.cc | 26 +++++++++++++++----------- src/spicy/spicyz/glue-compiler.h | 7 ++++++- 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/scripts/spicy/zeek_rt.hlt b/scripts/spicy/zeek_rt.hlt index a4e6f874ed..a238508b34 100644 --- a/scripts/spicy/zeek_rt.hlt +++ b/scripts/spicy/zeek_rt.hlt @@ -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 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; # (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>> labels) &cxxname="zeek::spicy::rt::create_enum_type" &have_prototype; declare public BroType create_record_type(string ns, string id, vector 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 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; diff --git a/src/spicy/runtime-support.cc b/src/spicy/runtime-support.cc index 4be7e14142..8d9fe3127b 100644 --- a/src/spicy/runtime-support.cc +++ b/src/spicy/runtime-support.cc @@ -126,25 +126,30 @@ TypePtr rt::create_record_type(const std::string& ns, const std::string& id, auto decls = std::make_unique(); - for ( const auto& [id, type, optional, log] : fields ) { + for ( const auto& f : fields ) { auto attrs = make_intrusive(nullptr, true, false); - if ( optional ) { + if ( f.is_optional ) { auto optional_ = make_intrusive(detail::ATTR_OPTIONAL); attrs->AddAttr(std::move(optional_)); } - if ( log ) { + if ( f.is_log ) { auto log_ = make_intrusive(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(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 value) { auto _ = hilti::rt::profiler::start("zeek/rt/create_table_type"); auto idx = make_intrusive(); diff --git a/src/spicy/runtime-support.h b/src/spicy/runtime-support.h index bc3c3cf067..5bd6178d13 100644 --- a/src/spicy/runtime-support.h +++ b/src/spicy/runtime-support.h @@ -151,9 +151,17 @@ extern TypePtr create_enum_type( const std::string& ns, const std::string& id, const hilti::rt::Vector>>& labels); -using RecordField = std::tuple; // (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& 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 value); extern TypePtr create_vector_type(const TypePtr& elem); diff --git a/src/spicy/spicyz/glue-compiler.cc b/src/spicy/spicyz/glue-compiler.cc index a95af83eeb..d49e878b9d 100644 --- a/src/spicy/spicyz/glue-compiler.cc +++ b/src/spicy/spicyz/glue-compiler.cc @@ -1335,6 +1335,12 @@ struct VisitorZeekType : hilti::visitor::PreOrder& id_ = {}) { @@ -1419,8 +1425,7 @@ struct VisitorZeekType : hilti::visitor::PreOrdernamespace_(), id()->local(), fields); @@ -1436,8 +1441,7 @@ struct VisitorZeekType : hilti::visitor::PreOrder 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 { if ( f.isTransient() || f.parseType().isA() ) 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) { diff --git a/src/spicy/spicyz/glue-compiler.h b/src/spicy/spicyz/glue-compiler.h index a7c05ec542..460dfb8117 100644 --- a/src/spicy/spicyz/glue-compiler.h +++ b/src/spicy/spicyz/glue-compiler.h @@ -201,7 +201,12 @@ public: /** Generates code to convert a HILTI type to a corresponding Zeek type at runtime. */ hilti::Result createZeekType(const hilti::Type& t, const hilti::ID& id) const; - using RecordField = std::tuple; /**< (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