diff --git a/CMakeLists.txt b/CMakeLists.txt index 37174c1fa0..722b74b295 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,22 @@ if (WIN32) set(CMAKE_TOOLCHAIN_FILE ${_toolchain} CACHE STRING "Vcpkg toolchain file") endif () +if (APPLE AND CMAKE_VERSION VERSION_GREATER_EQUAL 4.0.0 AND NOT CMAKE_OSX_SYSROOT) + # Spicy needs having CMAKE_OSX_SYSROOT point to the macOS SDK + # path, but starting with CMake 4.0 CMAKE_OSX_SYSROOT is not set + # automatically anymore. So we follow the guidance from the CMake 4.0 + # release notes here: + # + # Builds targeting macOS no longer choose any SDK or pass an "-isysroot" + # flag to the compiler by default. [...] users must now specify + # "-DCMAKE_OSX_SYSROOT=macosx" when configuring their build. + # + # Note that this needs to happen before the project() call below, meaning + # we cannot rely on the corresponding code inside the Spicy CMake + # configuration. + set(CMAKE_OSX_SYSROOT "macosx") +endif () + project(Zeek C CXX) # We want to set ENABLE_DEBUG to ON by default if the build type is Debug. diff --git a/auxil/spicy b/auxil/spicy index 1650d875a8..26421d12f1 160000 --- a/auxil/spicy +++ b/auxil/spicy @@ -1 +1 @@ -Subproject commit 1650d875a87accce61bb9d8cde7f51f033280acf +Subproject commit 26421d12f15d8b16ba6f385bbd47394cc9f9a0df diff --git a/scripts/spicy/zeek_rt.hlt b/scripts/spicy/zeek_rt.hlt index 3f4dd28adc..46906d8079 100644 --- a/scripts/spicy/zeek_rt.hlt +++ b/scripts/spicy/zeek_rt.hlt @@ -33,7 +33,7 @@ declare public BroType event_arg_type(EventHandlerPtr handler, uint<64> idx) &cx declare public Val to_val(any x, BroType target) &cxxname="zeek::spicy::rt::to_val" &have_prototype; 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_enum_type(string ns, string id, set>> 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; diff --git a/src/spicy/manager.cc b/src/spicy/manager.cc index db533a3030..4ade831e2f 100644 --- a/src/spicy/manager.cc +++ b/src/spicy/manager.cc @@ -691,7 +691,7 @@ void Manager::InitPostScript() { // event that will do it for us through a predefined handler. zeek::Args vals = Args(); vals.emplace_back(tag.AsVal()); - vals.emplace_back(zeek::spicy::rt::to_val(port_, base_type(TYPE_PORT))); + vals.emplace_back(zeek::spicy::rt::to_val(port_, &hilti::rt::type_info::port, base_type(TYPE_PORT))); EventHandlerPtr handler = event_registry->Register("spicy_analyzer_for_port"); event_mgr.Enqueue(handler, std::move(vals)); }; diff --git a/src/spicy/runtime-support.cc b/src/spicy/runtime-support.cc index 8140c1a0bf..edbb2b1614 100644 --- a/src/spicy/runtime-support.cc +++ b/src/spicy/runtime-support.cc @@ -108,7 +108,8 @@ std::string hilti::rt::detail::adl::to_string(const zeek::spicy::rt::ZeekTypeTag TypePtr rt::create_enum_type( const std::string& ns, const std::string& id, - const hilti::rt::Vector>>& labels) { + const hilti::rt::Set, std::optional>>>& + labels) { auto _ = hilti::rt::profiler::start("zeek/rt/create_enum_type"); if ( auto t = findType(TYPE_ENUM, ns, id) ) @@ -117,13 +118,14 @@ TypePtr rt::create_enum_type( auto etype = make_intrusive(ns + "::" + id); for ( auto [lid, lval] : labels ) { - auto name = ::hilti::rt::fmt("%s_%s", id, lid); + assert(lid && lval); + auto name = ::hilti::rt::fmt("%s_%s", id, *lid); - if ( lval == -1 ) + if ( *lval == -1 ) // Zeek's enum can't be negative, so swap in max_int for our Undef. lval = std::numeric_limits<::zeek_int_t>::max(); - etype->AddName(ns, name.c_str(), lval, true); + etype->AddName(ns, name.c_str(), *lval, true); } return std::move(etype); @@ -393,7 +395,7 @@ std::string rt::uid() { throw ValueUnavailable("uid() not available in current context"); } -std::tuple rt::conn_id() { +hilti::rt::Tuple rt::conn_id() { auto _ = hilti::rt::profiler::start("zeek/rt/conn_id"); static auto convert_address = [](const IPAddr& zaddr) -> hilti::rt::Address { @@ -424,10 +426,10 @@ std::tuple(hilti::rt::context::cookie()) ) { if ( auto c = cookie->protocol ) { const auto* conn = c->analyzer->Conn(); - return std::make_tuple(convert_address(conn->OrigAddr()), - convert_port(conn->OrigPort(), conn->ConnTransport()), - convert_address(conn->RespAddr()), - convert_port(conn->RespPort(), conn->ConnTransport())); + return hilti::rt::tuple::make(convert_address(conn->OrigAddr()), + convert_port(conn->OrigPort(), conn->ConnTransport()), + convert_address(conn->RespAddr()), + convert_port(conn->RespPort(), conn->ConnTransport())); } } diff --git a/src/spicy/runtime-support.h b/src/spicy/runtime-support.h index a73ae6edf5..0adcf8f885 100644 --- a/src/spicy/runtime-support.h +++ b/src/spicy/runtime-support.h @@ -14,10 +14,11 @@ #include #include -#include #include #include #include +#include +#include #include #include @@ -78,6 +79,8 @@ public: : TypeMismatch(hilti::rt::fmt("Event parameter mismatch, %s", msg)) {} ParameterMismatch(std::string_view have, const TypePtr& want, std::string_view location = "") : ParameterMismatch(_fmt(have, want)) {} + ParameterMismatch(const hilti::rt::TypeInfo& have, const TypePtr& want, std::string_view location = "") + : ParameterMismatch(_fmt(have.display, want)) {} private: static std::string _fmt(const std::string_view& have, const TypePtr& want) { @@ -169,7 +172,8 @@ extern TypePtr create_base_type(ZeekTypeTag tag); extern TypePtr create_enum_type( const std::string& ns, const std::string& id, - const hilti::rt::Vector>>& labels); + const hilti::rt::Set, std::optional>>>& + labels); struct RecordField { std::string id; /**< name of record field */ @@ -279,7 +283,7 @@ std::string uid(); /** * Returns the current connection's ID tuple. */ -std::tuple conn_id(); +hilti::rt::Tuple conn_id(); /** Instructs to Zeek to flip the directionality of the current connecction. */ void flip_roles(); @@ -488,39 +492,37 @@ void forward_packet(const hilti::rt::integer::safe& identifier); hilti::rt::Time network_time(); // Forward-declare to_val() functions. -template::value>* = nullptr> -ValPtr to_val(const T& t, const TypePtr& target); template -inline ValPtr to_val(const hilti::rt::Bitfield& v, const TypePtr& target); +ValPtr to_val(const hilti::rt::Tuple& t, const hilti::rt::TypeInfo* ti, const TypePtr& target); +template +inline ValPtr to_val(const hilti::rt::Bitfield& v, const hilti::rt::TypeInfo* ti, const TypePtr& target); template::value>* = nullptr> -ValPtr to_val(const T& t, const TypePtr& target); +ValPtr to_val(const T& t, const hilti::rt::TypeInfo* ti, const TypePtr& target); template::value>* = nullptr> -ValPtr to_val(const T& t, const TypePtr& target); +ValPtr to_val(const T& t, const hilti::rt::TypeInfo* ti, const TypePtr& target); template::value>* = nullptr> -ValPtr to_val(const T& t, const TypePtr& target); +ValPtr to_val(const T& t, const hilti::rt::TypeInfo* ti, const TypePtr& target); template -ValPtr to_val(const hilti::rt::Map& s, const TypePtr& target); +ValPtr to_val(const hilti::rt::Map& s, const hilti::rt::TypeInfo* ti, const TypePtr& target); template -ValPtr to_val(const hilti::rt::Set& s, const TypePtr& target); +ValPtr to_val(const hilti::rt::Set& s, const hilti::rt::TypeInfo* ti, const TypePtr& target); template -ValPtr to_val(const hilti::rt::Vector& v, const TypePtr& target); +ValPtr to_val(const hilti::rt::Vector& v, const hilti::rt::TypeInfo* ti, const TypePtr& target); template -ValPtr to_val(const std::optional& t, const TypePtr& target); -template -ValPtr to_val(const hilti::rt::DeferredExpression& t, const TypePtr& target); +ValPtr to_val(const std::optional& t, const hilti::rt::TypeInfo* ti, const TypePtr& target); template -ValPtr to_val(hilti::rt::integer::safe i, const TypePtr& target); +ValPtr to_val(hilti::rt::integer::safe i, const hilti::rt::TypeInfo* ti, const TypePtr& target); template -ValPtr to_val(const hilti::rt::ValueReference& t, const TypePtr& target); +ValPtr to_val(const hilti::rt::ValueReference& t, const hilti::rt::TypeInfo* ti, const TypePtr& target); -inline ValPtr to_val(const hilti::rt::Bool& b, const TypePtr& target); -inline ValPtr to_val(const hilti::rt::Address& d, const TypePtr& target); -inline ValPtr to_val(const hilti::rt::Bytes& b, const TypePtr& target); -inline ValPtr to_val(const hilti::rt::Interval& t, const TypePtr& target); -inline ValPtr to_val(const hilti::rt::Port& d, const TypePtr& target); -inline ValPtr to_val(const hilti::rt::Time& t, const TypePtr& target); -inline ValPtr to_val(const std::string& s, const TypePtr& target); -inline ValPtr to_val(double r, const TypePtr& target); +inline ValPtr to_val(const hilti::rt::Bool& b, const hilti::rt::TypeInfo* ti, const TypePtr& target); +inline ValPtr to_val(const hilti::rt::Address& d, const hilti::rt::TypeInfo* ti, const TypePtr& target); +inline ValPtr to_val(const hilti::rt::Bytes& b, const hilti::rt::TypeInfo* ti, const TypePtr& target); +inline ValPtr to_val(const hilti::rt::Interval& t, const hilti::rt::TypeInfo* ti, const TypePtr& target); +inline ValPtr to_val(const hilti::rt::Port& d, const hilti::rt::TypeInfo* ti, const TypePtr& target); +inline ValPtr to_val(const hilti::rt::Time& t, const hilti::rt::TypeInfo* ti, const TypePtr& target); +inline ValPtr to_val(const std::string& s, const hilti::rt::TypeInfo* ti, const TypePtr& target); +inline ValPtr to_val(double r, const hilti::rt::TypeInfo* ti, const TypePtr& target); /** * Converts a Spicy-side optional value to a Zeek value. This assumes the @@ -528,33 +530,18 @@ inline ValPtr to_val(double r, const TypePtr& target); * returned with ref count +1. */ template -inline ValPtr to_val(const std::optional& t, const TypePtr& target) { +inline ValPtr to_val(const std::optional& t, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( t.has_value() ) - return to_val(hilti::rt::optional::value(t), target); + return to_val(hilti::rt::optional::value(t), nullptr, target); return nullptr; } -/** - * Converts a Spicy-side DeferredExpression value to a Zeek value. Such - * result values are returned by the ``.?`` operator. If the result is not - * set, this will convert into nullptr (which the tuple-to-record to_val() - * picks up on). - */ -template -inline ValPtr to_val(const hilti::rt::DeferredExpression& t, const TypePtr& target) { - try { - return to_val(t(), target); - } catch ( const hilti::rt::AttributeNotSet& ) { - return nullptr; - } -} - /** * Converts a Spicy-side string to a Zeek value. The result is returned with * ref count +1. */ -inline ValPtr to_val(const std::string& s, const TypePtr& target) { +inline ValPtr to_val(const std::string& s, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_STRING ) throw ParameterMismatch("string", target); @@ -565,7 +552,7 @@ inline ValPtr to_val(const std::string& s, const TypePtr& target) { * Converts a Spicy-side bytes instance to a Zeek value. The result is returned with * ref count +1. */ -inline ValPtr to_val(const hilti::rt::Bytes& b, const TypePtr& target) { +inline ValPtr to_val(const hilti::rt::Bytes& b, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_STRING ) throw ParameterMismatch("string", target); @@ -577,7 +564,7 @@ inline ValPtr to_val(const hilti::rt::Bytes& b, const TypePtr& target) { * returned with ref count +1. */ template -inline ValPtr to_val(hilti::rt::integer::safe i, const TypePtr& target) { +inline ValPtr to_val(hilti::rt::integer::safe i, const hilti::rt::TypeInfo* ti, const TypePtr& target) { ValPtr v = nullptr; if constexpr ( std::is_unsigned::value ) { if ( target->Tag() == TYPE_COUNT ) @@ -604,9 +591,9 @@ inline ValPtr to_val(hilti::rt::integer::safe i, const TypePtr& target) { } template -ValPtr to_val(const hilti::rt::ValueReference& t, const TypePtr& target) { +ValPtr to_val(const hilti::rt::ValueReference& t, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( auto* x = t.get() ) - return to_val(*x, target); + return to_val(*x, nullptr, target); return nullptr; } @@ -615,7 +602,7 @@ ValPtr to_val(const hilti::rt::ValueReference& t, const TypePtr& target) { * Converts a Spicy-side signed bool to a Zeek value. The result is * returned with ref count +1. */ -inline ValPtr to_val(const hilti::rt::Bool& b, const TypePtr& target) { +inline ValPtr to_val(const hilti::rt::Bool& b, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_BOOL ) throw ParameterMismatch("bool", target); @@ -626,7 +613,7 @@ inline ValPtr to_val(const hilti::rt::Bool& b, const TypePtr& target) { * Converts a Spicy-side real to a Zeek value. The result is returned with * ref count +1. */ -inline ValPtr to_val(double r, const TypePtr& target) { +inline ValPtr to_val(double r, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_DOUBLE ) throw ParameterMismatch("double", target); @@ -637,7 +624,7 @@ inline ValPtr to_val(double r, const TypePtr& target) { * Converts a Spicy-side address to a Zeek value. The result is returned with * ref count +1. */ -inline ValPtr to_val(const hilti::rt::Address& d, const TypePtr& target) { +inline ValPtr to_val(const hilti::rt::Address& d, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_ADDR ) throw ParameterMismatch("addr", target); @@ -654,7 +641,7 @@ inline ValPtr to_val(const hilti::rt::Address& d, const TypePtr& target) { * Converts a Spicy-side address to a Zeek value. The result is returned with * ref count +1. */ -inline ValPtr to_val(const hilti::rt::Port& p, const TypePtr& target) { +inline ValPtr to_val(const hilti::rt::Port& p, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_PORT ) throw ParameterMismatch("port", target); @@ -673,7 +660,7 @@ inline ValPtr to_val(const hilti::rt::Port& p, const TypePtr& target) { * Converts a Spicy-side time to a Zeek value. The result is returned with * ref count +1. */ -inline ValPtr to_val(const hilti::rt::Interval& i, const TypePtr& target) { +inline ValPtr to_val(const hilti::rt::Interval& i, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_INTERVAL ) throw ParameterMismatch("interval", target); @@ -684,7 +671,7 @@ inline ValPtr to_val(const hilti::rt::Interval& i, const TypePtr& target) { * Converts a Spicy-side time to a Zeek value. The result is returned with * ref count +1. */ -inline ValPtr to_val(const hilti::rt::Time& t, const TypePtr& target) { +inline ValPtr to_val(const hilti::rt::Time& t, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_TIME ) throw ParameterMismatch("time", target); @@ -696,14 +683,14 @@ inline ValPtr to_val(const hilti::rt::Time& t, const TypePtr& target) { * ref count +1. */ template -inline ValPtr to_val(const hilti::rt::Vector& v, const TypePtr& target) { +inline ValPtr to_val(const hilti::rt::Vector& v, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_VECTOR && target->Tag() != TYPE_LIST ) throw ParameterMismatch("expected vector or list", target); auto vt = cast_intrusive(target); auto zv = make_intrusive(vt); for ( const auto& i : v ) - zv->Assign(zv->Size(), to_val(i, vt->Yield())); + zv->Assign(zv->Size(), to_val(i, nullptr, vt->Yield())); return std::move(zv); } @@ -713,10 +700,7 @@ inline ValPtr to_val(const hilti::rt::Vector& v, const TypePtr& ta * ref count +1. */ template -inline ValPtr to_val(const hilti::rt::Map& m, const TypePtr& target) { - if constexpr ( hilti::rt::is_tuple::value ) - throw ParameterMismatch("internal error: sets with tuples not yet supported in to_val()"); - +inline ValPtr to_val(const hilti::rt::Map& m, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_TABLE ) throw ParameterMismatch("map", target); @@ -730,8 +714,8 @@ inline ValPtr to_val(const hilti::rt::Map& m, const TypePtr& target) { auto zv = make_intrusive(tt); for ( const auto& i : m ) { - auto k = to_val(i.first, tt->GetIndexTypes()[0]); - auto v = to_val(i.second, tt->Yield()); + auto k = to_val(i.first, nullptr, tt->GetIndexTypes()[0]); + auto v = to_val(i.second, nullptr, tt->Yield()); zv->Assign(std::move(k), std::move(v)); } @@ -743,7 +727,7 @@ inline ValPtr to_val(const hilti::rt::Map& m, const TypePtr& target) { * ref count +1. */ template -inline ValPtr to_val(const hilti::rt::Set& s, const TypePtr& target) { +inline ValPtr to_val(const hilti::rt::Set& s, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_TABLE ) throw ParameterMismatch("set", target); @@ -754,15 +738,11 @@ inline ValPtr to_val(const hilti::rt::Set& s, const TypePtr& target) { auto zv = make_intrusive(tt); for ( const auto& i : s ) { - if constexpr ( hilti::rt::is_tuple::value ) - throw ParameterMismatch("internal error: sets with tuples not yet supported in to_val()"); - else { - if ( tt->GetIndexTypes().size() != 1 ) - throw ParameterMismatch("set with non-tuple elements", target); + if ( tt->GetIndexTypes().size() != 1 ) + throw ParameterMismatch("set with non-tuple elements", target); - auto idx = to_val(i, tt->GetIndexTypes()[0]); - zv->Assign(std::move(idx), nullptr); - } + auto idx = to_val(i, nullptr, tt->GetIndexTypes()[0]); + zv->Assign(std::move(idx), nullptr); } return zv; @@ -820,18 +800,11 @@ inline void set_record_field(RecordVal* rval, const IntrusivePtr& rt if ( x.has_value() ) set_record_field(rval, rtype, idx, *x); } - else if constexpr ( is_instance::value ) { - try { - set_record_field(rval, rtype, idx, x()); - } catch ( const hilti::rt::AttributeNotSet& ) { - // leave unset - } - } else { ValPtr v = nullptr; // This may return a nullptr in cases where the field is to be left unset. - v = to_val(x, rtype->GetFieldType(idx)); + v = to_val(x, nullptr, rtype->GetFieldType(idx)); if ( v ) rval->Assign(idx, v); @@ -848,14 +821,14 @@ inline void set_record_field(RecordVal* rval, const IntrusivePtr& rt * Converts a Spicy-side tuple to a Zeek record value. The result is returned * with ref count +1. */ -template::value>*> -inline ValPtr to_val(const T& t, const TypePtr& target) { +template +ValPtr to_val(const hilti::rt::Tuple& t, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_RECORD ) throw ParameterMismatch("tuple", target); auto rtype = cast_intrusive(target); - if ( std::tuple_size::value != rtype->NumFields() ) + if ( sizeof...(Ts) != rtype->NumFields() ) throw ParameterMismatch("tuple", target); auto rval = make_intrusive(rtype); @@ -870,7 +843,7 @@ inline ValPtr to_val(const T& t, const TypePtr& target) { * with ref count +1. */ template -inline ValPtr to_val(const hilti::rt::Bitfield& v, const TypePtr& target) { +inline ValPtr to_val(const hilti::rt::Bitfield& v, const hilti::rt::TypeInfo* ti, const TypePtr& target) { using Bitfield = hilti::rt::Bitfield; if ( target->Tag() != TYPE_RECORD ) @@ -903,7 +876,7 @@ constexpr bool is_optional = is_optional_impl::value>*> -inline ValPtr to_val(const T& t, const TypePtr& target) { +inline ValPtr to_val(const T& t, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_RECORD ) throw ParameterMismatch("struct", target); @@ -958,7 +931,7 @@ inline ValPtr to_val(const T& t, const TypePtr& target) { } /** Maps HILTI's `Protocol` enum to Zeek's `transport_proto` enum. */ -inline ValPtr to_val_for_transport_proto(int64_t val, const TypePtr& target) { +inline ValPtr to_val_for_transport_proto(int64_t val, const hilti::rt::TypeInfo* ti, const TypePtr& target) { switch ( val ) { case hilti::rt::Protocol::TCP: return id::transport_proto->GetEnumVal(::TransportProto::TRANSPORT_TCP); case hilti::rt::Protocol::UDP: return id::transport_proto->GetEnumVal(::TransportProto::TRANSPORT_UDP); @@ -975,7 +948,7 @@ inline ValPtr to_val_for_transport_proto(int64_t val, const TypePtr& target) { * with ref count +1. */ template::value>*> -inline ValPtr to_val(const T& t, const TypePtr& target) { +inline ValPtr to_val(const T& t, const hilti::rt::TypeInfo* ti, const TypePtr& target) { if ( target->Tag() != TYPE_ENUM ) throw ParameterMismatch("enum", target); @@ -989,7 +962,7 @@ inline ValPtr to_val(const T& t, const TypePtr& target) { if ( ! std::is_same_v ) throw ParameterMismatch(hilti::rt::demangle(typeid(t).name()), target); - return to_val_for_transport_proto(it, target); + return to_val_for_transport_proto(it, nullptr, target); } // Zeek's enum can't be negative, so we swap in max_int for our Undef (-1). @@ -1243,28 +1216,28 @@ inline hilti::rt::Bool record_has_field(const std::string& name, const std::stri /** Checks if a Zeek set contains a given element. Throws on errors. */ template -::hilti::rt::Bool set_contains(const ValSetPtr& v, const T& key) { +::hilti::rt::Bool set_contains(const ValSetPtr& v, const T& key, const hilti::rt::TypeInfo* ktype) { auto index = v->GetType()->AsTableType()->GetIndexTypes()[0]; - return (v->Find(to_val(key, index)) != nullptr); + return (v->Find(to_val(key, ktype, index)) != nullptr); } /** Checks if a Zeek set contains a given element. Throws on errors. */ template -::hilti::rt::Bool set_contains(const std::string& name, const T& key) { - return set_contains(get_set(name), key); +::hilti::rt::Bool set_contains(const std::string& name, const T& key, const hilti::rt::TypeInfo* ktype) { + return set_contains(get_set(name), key, ktype); } /** Checks if a Zeek table contains a given element. Throws on errors. */ template -::hilti::rt::Bool table_contains(const ValTablePtr& v, const T& key) { +::hilti::rt::Bool table_contains(const ValTablePtr& v, const T& key, const hilti::rt::TypeInfo* ktype) { auto index = v->GetType()->AsTableType()->GetIndexTypes()[0]; - return (v->Find(to_val(key, index)) != nullptr); + return (v->Find(to_val(key, ktype, index)) != nullptr); } /** Check if a Zeek table contains a given element. Throws on errors. */ template -::hilti::rt::Bool table_contains(const std::string& name, const T& key) { - return table_contains(get_table(name), key); +::hilti::rt::Bool table_contains(const std::string& name, const T& key, const hilti::rt::TypeInfo* ktype) { + return table_contains(get_table(name), key, ktype); } /** @@ -1272,9 +1245,10 @@ template * not exist. Throws on other errors. */ template -std::optional<::zeek::ValPtr> table_lookup(const zeek::spicy::rt::ValTablePtr& v, const T& key) { +std::optional<::zeek::ValPtr> table_lookup(const zeek::spicy::rt::ValTablePtr& v, const T& key, + const hilti::rt::TypeInfo* ktype) { auto index = v->GetType()->AsTableType()->GetIndexTypes()[0]; - if ( auto x = v->FindOrDefault(to_val(key, index)) ) + if ( auto x = v->FindOrDefault(to_val(key, ktype, index)) ) return x; else return {}; @@ -1285,8 +1259,8 @@ std::optional<::zeek::ValPtr> table_lookup(const zeek::spicy::rt::ValTablePtr& v * not exist. Throws on other errors. */ template -std::optional<::zeek::ValPtr> table_lookup(const std::string& name, const T& key) { - return table_lookup(get_table(name), key); +std::optional<::zeek::ValPtr> table_lookup(const std::string& name, const T& key, const hilti::rt::TypeInfo* ktype) { + return table_lookup(get_table(name), key, ktype); } /** Returns a Zeek vector element. Throws on errors. */ diff --git a/src/spicy/spicyz/glue-compiler.cc b/src/spicy/spicyz/glue-compiler.cc index 33f68fea2c..100a40b4f3 100644 --- a/src/spicy/spicyz/glue-compiler.cc +++ b/src/spicy/spicyz/glue-compiler.cc @@ -1204,33 +1204,12 @@ bool GlueCompiler::PopulateEvents() { #include -// Helper visitor to wrap expressions using the TryMember operator into a -// "deferred" expression. -class WrapTryMemberVisitor : public spicy::visitor::MutatingPostOrder { -public: - WrapTryMemberVisitor(Builder* builder, bool catch_exception) - : spicy::visitor::MutatingPostOrder(builder, logging::debug::GlueCompiler), _catch_exception(catch_exception) {} - - void operator()(hilti::expression::UnresolvedOperator* n) final { - if ( n->kind() == hilti::operator_::Kind::TryMember ) - replaceNode(n, builder()->expressionDeferred(n->as(), _catch_exception), "wrap .?"); - } - -private: - bool _catch_exception; -}; - static hilti::Result parseArgument(Builder* builder, const std::string& expression, bool catch_exception, const hilti::Meta& meta) { auto expr = ::spicy::builder::parseExpression(builder, expression, meta); if ( ! expr ) return hilti::result::Error(hilti::util::fmt("error parsing event argument expression '%s'", expression)); - // If the expression uses the ".?" operator, we need to defer evaluation - // so that we can handle potential exceptions at runtime. - auto v = WrapTryMemberVisitor(builder, catch_exception); - spicy::visitor::visit(v, *expr); - return expr; } @@ -1538,7 +1517,7 @@ struct VisitorZeekType : spicy::visitor::PreOrder { }); auto tmp = builder->addTmp(tmpName("labels", id()), - builder->typeVector( + builder->typeSet( builder->qualifiedType(builder->typeTuple(hilti::QualifiedTypes{ builder->qualifiedType(builder->typeString(), hilti::Constness::Const), @@ -1547,9 +1526,8 @@ struct VisitorZeekType : spicy::visitor::PreOrder { hilti::Constness::Const))); for ( const auto& l : t->labels() ) - builder->addMemberCall(tmp, "push_back", - {builder->tuple( - {builder->stringLiteral(l->id().str()), builder->integer(l->value())})}); + builder->addExpression(builder->add(tmp, builder->tuple({builder->stringMutable(l->id().str()), + builder->integer(l->value())}))); result(builder->call("zeek_rt::create_enum_type", {builder->stringMutable(id().namespace_().str()), builder->stringMutable(id().local().str()), tmp})); diff --git a/testing/btest/Baseline/spicy.preprocessor-spicy/output b/testing/btest/Baseline/spicy.preprocessor-spicy/output index 5d241aaa39..72e58ef2fc 100644 --- a/testing/btest/Baseline/spicy.preprocessor-spicy/output +++ b/testing/btest/Baseline/spicy.preprocessor-spicy/output @@ -1,7 +1,7 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. == spicyz - ::hilti::rt::print("have zeek"s, ::hilti::rt::Bool(true)); - ::hilti::rt::print("have spicy version"s, ::hilti::rt::Bool(true)); - ::hilti::rt::print("have spicy version >= 0.4"s, ::hilti::rt::Bool(true)); - ::hilti::rt::print("not have spicy version >= 4"s, ::hilti::rt::Bool(true)); - ::hilti::rt::print("have zeek and zeek version > 1.0"s, ::hilti::rt::Bool(true)); + ::hilti::rt::print("have zeek"s, &::hilti::rt::type_info::string, ::hilti::rt::Bool(true)); + ::hilti::rt::print("have spicy version"s, &::hilti::rt::type_info::string, ::hilti::rt::Bool(true)); + ::hilti::rt::print("have spicy version >= 0.4"s, &::hilti::rt::type_info::string, ::hilti::rt::Bool(true)); + ::hilti::rt::print("not have spicy version >= 4"s, &::hilti::rt::type_info::string, ::hilti::rt::Bool(true)); + ::hilti::rt::print("have zeek and zeek version > 1.0"s, &::hilti::rt::type_info::string, ::hilti::rt::Bool(true)); diff --git a/testing/btest/Baseline/spicy.tuple-arg/output b/testing/btest/Baseline/spicy.tuple-arg/output index 20fbee3d84..6181899f5e 100644 --- a/testing/btest/Baseline/spicy.tuple-arg/output +++ b/testing/btest/Baseline/spicy.tuple-arg/output @@ -5,5 +5,5 @@ [i=4, s=] [zeek] [SPICY_SSH/3/orig] -> event ssh::banner((1, b"OpenSSH_3.8.1p1")) [zeek] [SPICY_SSH/3/orig] -> event ssh::banner((2, b"OpenSSH_3.8.1p1")) -[zeek] [SPICY_SSH/3/orig] -> event ssh::banner((3, b"")) +[zeek] [SPICY_SSH/3/orig] -> event ssh::banner((3, (not set))) [zeek] [SPICY_SSH/3/orig] -> event ssh::banner((4, Null))