diff --git a/CHANGES b/CHANGES index cf1d554c4..abcf641a0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,16 @@ +1.13.0-dev.45 | 2025-01-08 17:15:06 +0100 + + * GH-1936: Migrate `Attribute::Kind` to enum stringification framework. (Benjamin Bannier, Corelight) + + This patch performs cleans up the recently added `Attribute::Kind` enum + so it is properly integrated. + + - introduce a standalone enum `attribute::Kind` outside of the + `Attribute` class + - use enum helpers for conversion from and to string + + Closes #1936. + 1.13.0-dev.43 | 2025-01-08 09:39:45 +0100 * Drop unused includes. (Benjamin Bannier, Corelight) diff --git a/VERSION b/VERSION index 8f7acc90a..aa03b33e4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.13.0-dev.43 +1.13.0-dev.45 diff --git a/hilti/toolchain/include/ast/attribute.h b/hilti/toolchain/include/ast/attribute.h index 4bdc36773..8e9f7caee 100644 --- a/hilti/toolchain/include/ast/attribute.h +++ b/hilti/toolchain/include/ast/attribute.h @@ -3,65 +3,126 @@ #pragma once #include -#include #include #include +#include #include #include #include #include +#include namespace hilti { +namespace attribute { + +enum class Kind { + Eod, + Until, + UntilIncluding, + ParseAt, + ParseFrom, + Size, + MaxSize, + IPv4, + IPv6, + Type, + Count, + Synchronize, + Default, + Anonymous, + Internal, + Optional, + Static, + NoEmit, + OnHeap, + Nosub, + Cxxname, + HavePrototype, + Priority, + Convert, + While, + Requires, + ByteOrder, + BitOrder, + Chunked, + Originator, + Responder, + Try, + NeededByFeature, + RequiresTypeFeature, + AlwaysEmit, + Transient, + Anchor, + + // Hooks + Debug, + Error, + Foreach, +}; + +namespace detail { +constexpr util::enum_::Value AttributeKinds[] = { + {Kind::Eod, "&eod"}, + {Kind::Until, "&until"}, + {Kind::UntilIncluding, "&until-including"}, + {Kind::ParseAt, "&parse-at"}, + {Kind::ParseFrom, "&parse-from"}, + {Kind::Size, "&size"}, + {Kind::MaxSize, "&max-size"}, + {Kind::IPv4, "&ipv4"}, + {Kind::IPv6, "&ipv6"}, + {Kind::Type, "&type"}, + {Kind::Count, "&count"}, + {Kind::Synchronize, "&synchronize"}, + {Kind::Default, "&default"}, + {Kind::Anonymous, "&anonymous"}, + {Kind::Internal, "&internal"}, + {Kind::Optional, "&optional"}, + {Kind::Static, "&static"}, + {Kind::NoEmit, "&no-emit"}, + {Kind::OnHeap, "&on-heap"}, + {Kind::Nosub, "&nosub"}, + {Kind::Cxxname, "&cxxname"}, + {Kind::HavePrototype, "&have_prototype"}, + {Kind::Priority, "&priority"}, + {Kind::Convert, "&convert"}, + {Kind::While, "&while"}, + {Kind::Requires, "&requires"}, + {Kind::ByteOrder, "&byte-order"}, + {Kind::BitOrder, "&bit-order"}, + {Kind::Chunked, "&chunked"}, + {Kind::Originator, "&originator"}, + {Kind::Responder, "&responder"}, + {Kind::Try, "&try"}, + {Kind::NeededByFeature, "&needed-by-feature"}, + {Kind::RequiresTypeFeature, "&requires-type-feature"}, + {Kind::AlwaysEmit, "&always-emit"}, + {Kind::Transient, "&transient"}, + {Kind::Anchor, "&anchor"}, + {Kind::Debug, "%debug"}, + {Kind::Error, "%error"}, + {Kind::Foreach, "foreach"}, +}; +} + +constexpr auto to_string(Kind kind) { return util::enum_::to_string(kind, detail::AttributeKinds); } + +/** Returns whether `kind` is in `kinds` */ +inline bool isOneOf(Kind kind, std::initializer_list kinds) { + return std::find(kinds.begin(), kinds.end(), kind) != kinds.end(); +} + +namespace kind { +constexpr auto from_string(const std::string_view& s) { return util::enum_::from_string(s, detail::AttributeKinds); } +} // namespace kind + +} // namespace attribute + /** AST node for an attribute. */ class Attribute : public Node { public: - enum class Kind { - Eod, - Until, - UntilIncluding, - ParseAt, - ParseFrom, - Size, - MaxSize, - IPv4, - IPv6, - Type, - Count, - Synchronize, - Default, - Anonymous, - Internal, - Optional, - Static, - NoEmit, - OnHeap, - Nosub, - Cxxname, - HavePrototype, - Priority, - Convert, - While, - Requires, - ByteOrder, - BitOrder, - Chunked, - Originator, - Responder, - Try, - NeededByFeature, - RequiresTypeFeature, - AlwaysEmit, - Transient, - Anchor, - - // Hooks - Debug, - Error, - Foreach, - }; - /** Returns the kind of the attribute, derived from its tag. */ const auto& kind() const { return _kind; } @@ -114,22 +175,8 @@ class Attribute : public Node { */ Result coerceValueTo(Builder* builder, QualifiedType* dst); - /** Returns whether `kind` is in `kinds` */ - static bool isOneOf(Kind kind, std::initializer_list kinds) { - return std::find(kinds.begin(), kinds.end(), kind) != kinds.end(); - } - - /** Transforms a tag name into the appropriate enum value. */ - static std::optional tagToKind(std::string_view tag); - - /** Transforms a kind into its name for diagnostics. */ - static std::string_view kindToString(Kind kind); - - /** A non-static alternative to get an attribute's string representation. */ - std::string_view attributeName() const { return kindToString(_kind); } - node::Properties properties() const final { - auto p = node::Properties{{"tag", std::string{attributeName()}}}; + auto p = node::Properties{{"tag", to_string(kind())}}; return Node::properties() + std::move(p); } @@ -141,7 +188,7 @@ class Attribute : public Node { * @param v node representing the argument to associate with the attribute; must be an expression * @param m meta data to associate with the node */ - static auto create(ASTContext* ctx, Kind kind, Expression* v, const Meta& m = Meta()) { + static auto create(ASTContext* ctx, attribute::Kind kind, Expression* v, const Meta& m = Meta()) { return ctx->make(ctx, {v}, kind, m); } @@ -151,10 +198,12 @@ class Attribute : public Node { * @param kind the attribute's internal representation * @param m meta data to associate with the node */ - static auto create(ASTContext* ctx, Kind kind, const Meta& m = Meta()) { return create(ctx, kind, nullptr, m); } + static auto create(ASTContext* ctx, attribute::Kind kind, const Meta& m = Meta()) { + return create(ctx, kind, nullptr, m); + } protected: - Attribute(ASTContext* ctx, Nodes children, Kind kind, Meta m = Meta()) + Attribute(ASTContext* ctx, Nodes children, attribute::Kind kind, Meta m = Meta()) : Node(ctx, NodeTags, std::move(children), std::move(m)), _kind(kind) {} std::string _dump() const override; @@ -162,49 +211,7 @@ class Attribute : public Node { HILTI_NODE_0(Attribute, final); private: - Kind _kind; - static inline std::map _attr_map{ - {"&eod", Attribute::Kind::Eod}, - {"&until", Attribute::Kind::Until}, - {"&until-including", Attribute::Kind::UntilIncluding}, - {"&parse-at", Attribute::Kind::ParseAt}, - {"&parse-from", Attribute::Kind::ParseFrom}, - {"&size", Attribute::Kind::Size}, - {"&max-size", Attribute::Kind::MaxSize}, - {"&ipv4", Attribute::Kind::IPv4}, - {"&ipv6", Attribute::Kind::IPv6}, - {"&type", Attribute::Kind::Type}, - {"&count", Attribute::Kind::Count}, - {"&synchronize", Attribute::Kind::Synchronize}, - {"&default", Attribute::Kind::Default}, - {"&anonymous", Attribute::Kind::Anonymous}, - {"&internal", Attribute::Kind::Internal}, - {"&optional", Attribute::Kind::Optional}, - {"&static", Attribute::Kind::Static}, - {"&no-emit", Attribute::Kind::NoEmit}, - {"&on-heap", Attribute::Kind::OnHeap}, - {"&nosub", Attribute::Kind::Nosub}, - {"&cxxname", Attribute::Kind::Cxxname}, - {"&have_prototype", Attribute::Kind::HavePrototype}, - {"&priority", Attribute::Kind::Priority}, - {"&convert", Attribute::Kind::Convert}, - {"&while", Attribute::Kind::While}, - {"&requires", Attribute::Kind::Requires}, - {"&byte-order", Attribute::Kind::ByteOrder}, - {"&bit-order", Attribute::Kind::BitOrder}, - {"&chunked", Attribute::Kind::Chunked}, - {"&originator", Attribute::Kind::Originator}, - {"&responder", Attribute::Kind::Responder}, - {"&try", Attribute::Kind::Try}, - {"&needed-by-feature", Attribute::Kind::NeededByFeature}, - {"&requires-type-feature", Attribute::Kind::RequiresTypeFeature}, - {"&always-emit", Attribute::Kind::AlwaysEmit}, - {"&transient", Attribute::Kind::Transient}, - {"&anchor", Attribute::Kind::Anchor}, - {"%debug", Attribute::Kind::Debug}, - {"%error", Attribute::Kind::Error}, - {"foreach", Attribute::Kind::Foreach}, - }; + attribute::Kind _kind; }; /** AST node holding a set of `Attribute` nodes. */ @@ -219,21 +226,21 @@ class AttributeSet : public Node { * * @return attribute if found */ - Attribute* find(Attribute::Kind kind) const; + Attribute* find(attribute::Kind kind) const; /** * Retrieves all attributes with a given kind from the set. * * @return all attributes with matching kind */ - hilti::node::Set findAll(Attribute::Kind kind) const; + hilti::node::Set findAll(attribute::Kind kind) const; /** * Returns true if there's an attribute with a given kind in the set. * * @param true if found */ - bool has(Attribute::Kind kind) const { return find(kind) != nullptr; } + bool has(attribute::Kind kind) const { return find(kind) != nullptr; } /** Adds an attribute to the set. */ void add(ASTContext* ctx, Attribute* a) { @@ -243,7 +250,7 @@ class AttributeSet : public Node { } /** Removes all attributes of the given kind. */ - void remove(Attribute::Kind kind); + void remove(attribute::Kind kind); /** Returns true if the set has at least one element. */ operator bool() const { return ! attributes().empty(); } diff --git a/hilti/toolchain/include/ast/builder/node-factory.h b/hilti/toolchain/include/ast/builder/node-factory.h index 767c0b203..ce9d9d530 100644 --- a/hilti/toolchain/include/ast/builder/node-factory.h +++ b/hilti/toolchain/include/ast/builder/node-factory.h @@ -24,10 +24,10 @@ class NodeFactory { /** Returns the AST context in use for creating nodes. */ ASTContext* context() const { return _context; } - auto attribute(hilti::Attribute::Kind kind, Expression* v, const Meta& m = Meta()) { + auto attribute(hilti::attribute::Kind kind, Expression* v, const Meta& m = Meta()) { return hilti::Attribute::create(context(), kind, v, m); } - auto attribute(hilti::Attribute::Kind kind, const Meta& m = Meta()) { + auto attribute(hilti::attribute::Kind kind, const Meta& m = Meta()) { return hilti::Attribute::create(context(), kind, m); } auto attributeSet(Attributes attrs = {}, Meta m = Meta()) { diff --git a/hilti/toolchain/include/ast/ctors/regexp.h b/hilti/toolchain/include/ast/ctors/regexp.h index e2d334e1b..b21d50a8f 100644 --- a/hilti/toolchain/include/ast/ctors/regexp.h +++ b/hilti/toolchain/include/ast/ctors/regexp.h @@ -21,7 +21,7 @@ class RegExp : public Ctor { /** * Returns true if this pattern does not need support for capturing groups. */ - bool isNoSub() const { return attributes()->find(hilti::Attribute::Kind::Nosub) != nullptr; } + bool isNoSub() const { return attributes()->find(hilti::attribute::Kind::Nosub) != nullptr; } QualifiedType* type() const final { return child(0); } diff --git a/hilti/toolchain/include/ast/declarations/field.h b/hilti/toolchain/include/ast/declarations/field.h index 4ee09ee06..f3891d948 100644 --- a/hilti/toolchain/include/ast/declarations/field.h +++ b/hilti/toolchain/include/ast/declarations/field.h @@ -48,17 +48,17 @@ class Field : public Declaration { } hilti::Expression* default_() const { - if ( auto a = attributes()->find(hilti::Attribute::Kind::Default) ) + if ( auto a = attributes()->find(hilti::attribute::Kind::Default) ) return *a->valueAsExpression(); else return {}; } - auto isAnonymous() const { return attributes()->find(hilti::Attribute::Kind::Anonymous) != nullptr; } - auto isInternal() const { return attributes()->find(hilti::Attribute::Kind::Internal) != nullptr; } - auto isOptional() const { return attributes()->find(hilti::Attribute::Kind::Optional) != nullptr; } - auto isStatic() const { return attributes()->find(hilti::Attribute::Kind::Static) != nullptr; } - auto isNoEmit() const { return attributes()->find(hilti::Attribute::Kind::NoEmit) != nullptr; } + auto isAnonymous() const { return attributes()->find(hilti::attribute::Kind::Anonymous) != nullptr; } + auto isInternal() const { return attributes()->find(hilti::attribute::Kind::Internal) != nullptr; } + auto isOptional() const { return attributes()->find(hilti::attribute::Kind::Optional) != nullptr; } + auto isStatic() const { return attributes()->find(hilti::attribute::Kind::Static) != nullptr; } + auto isNoEmit() const { return attributes()->find(hilti::attribute::Kind::NoEmit) != nullptr; } auto linkedTypeIndex() const { return _linked_type_index; } @@ -78,7 +78,7 @@ class Field : public Declaration { if ( ! attrs ) attrs = AttributeSet::create(ctx); - if ( attrs->has(hilti::Attribute::Kind::Static) ) + if ( attrs->has(hilti::attribute::Kind::Static) ) // make it assignable type = type->recreateAsLhs(ctx); diff --git a/hilti/toolchain/include/ast/declarations/type.h b/hilti/toolchain/include/ast/declarations/type.h index 294f7b4db..be816e399 100644 --- a/hilti/toolchain/include/ast/declarations/type.h +++ b/hilti/toolchain/include/ast/declarations/type.h @@ -18,7 +18,7 @@ class Type : public Declaration { bool isOnHeap() const { if ( auto x = attributes() ) - return x->find(hilti::Attribute::Kind::OnHeap) != nullptr; + return x->find(hilti::attribute::Kind::OnHeap) != nullptr; else return false; } diff --git a/hilti/toolchain/include/ast/function.h b/hilti/toolchain/include/ast/function.h index 3b0855fb4..6829638fe 100644 --- a/hilti/toolchain/include/ast/function.h +++ b/hilti/toolchain/include/ast/function.h @@ -50,7 +50,7 @@ class Function : public Node { auto body() const { return child(1); } auto attributes() const { return child(2); } auto callingConvention() const { return _cc; } - auto isStatic() const { return attributes()->find(hilti::Attribute::Kind::Static) != nullptr; } + auto isStatic() const { return attributes()->find(hilti::attribute::Kind::Static) != nullptr; } void setBody(ASTContext* ctx, Statement* b) { setChild(ctx, 1, b); } void setID(ID id) { _id = std::move(id); } diff --git a/hilti/toolchain/src/ast/attribute.cc b/hilti/toolchain/src/ast/attribute.cc index d3e7a0dfe..4e821b144 100644 --- a/hilti/toolchain/src/ast/attribute.cc +++ b/hilti/toolchain/src/ast/attribute.cc @@ -1,7 +1,5 @@ // Copyright (c) 2020-2023 by the Zeek Project. See LICENSE for details. -#include - #include #include #include @@ -16,28 +14,28 @@ using namespace hilti; Result Attribute::valueAsExpression() const { if ( ! hasValue() ) - return result::Error(hilti::util::fmt("attribute '%s' requires an expression", attributeName())); + return result::Error(hilti::util::fmt("attribute '%s' requires an expression", to_string(kind()))); if ( ! value()->isA() ) - return result::Error(hilti::util::fmt("value for attribute '%s' must be an expression", attributeName())); + return result::Error(hilti::util::fmt("value for attribute '%s' must be an expression", to_string(kind()))); return {value()->as()}; } Result Attribute::valueAsString() const { if ( ! hasValue() ) - return result::Error(hilti::util::fmt("attribute '%s' requires a string", attributeName())); + return result::Error(hilti::util::fmt("attribute '%s' requires a string", to_string(kind()))); if ( auto e = value()->tryAs() ) if ( auto s = e->ctor()->tryAs() ) return s->value(); - return result::Error(hilti::util::fmt("value for attribute '%s' must be a string", attributeName())); + return result::Error(hilti::util::fmt("value for attribute '%s' must be a string", to_string(kind()))); } Result Attribute::valueAsInteger() const { if ( ! hasValue() ) - return result::Error(hilti::util::fmt("attribute '%s' requires an integer", attributeName())); + return result::Error(hilti::util::fmt("attribute '%s' requires an integer", to_string(kind()))); if ( auto e = value()->tryAs() ) { if ( auto s = e->ctor()->tryAs() ) @@ -47,7 +45,7 @@ Result Attribute::valueAsInteger() const { return static_cast(s->value()); } - return result::Error(hilti::util::fmt("value for attribute '%s' must be an integer", attributeName())); + return result::Error(hilti::util::fmt("value for attribute '%s' must be an integer", to_string(kind()))); } Result Attribute::coerceValueTo(Builder* builder, QualifiedType* dst) { @@ -58,7 +56,7 @@ Result Attribute::coerceValueTo(Builder* builder, QualifiedType* dst) { auto ne = coerceExpression(builder, *e, dst); if ( ! ne.coerced ) return result::Error(hilti::util::fmt("cannot coerce attribute's expression from type '%s' to '%s' (%s)", - *(*e)->type(), *dst, attributeName())); + *(*e)->type(), *dst, to_string(kind()))); if ( ! ne.nexpr ) return false; @@ -70,27 +68,11 @@ Result Attribute::coerceValueTo(Builder* builder, QualifiedType* dst) { return result::Error("cannot coerce non-expression attribute value"); } -std::optional Attribute::tagToKind(std::string_view tag) { - if ( auto found = _attr_map.find(tag); found != _attr_map.end() ) - return found->second; - - return {}; -} - -std::string_view Attribute::kindToString(Kind kind) { - for ( auto&& [name, tag] : _attr_map ) { - if ( tag == kind ) - return name; - } - - util::cannotBeReached(); -} - std::string Attribute::_dump() const { return ""; } std::string AttributeSet::_dump() const { return ""; } -Attribute* AttributeSet::find(Attribute::Kind kind) const { +Attribute* AttributeSet::find(attribute::Kind kind) const { for ( const auto& a : attributes() ) if ( a->kind() == kind ) return a; @@ -98,7 +80,7 @@ Attribute* AttributeSet::find(Attribute::Kind kind) const { return {}; } -hilti::node::Set AttributeSet::findAll(Attribute::Kind kind) const { +hilti::node::Set AttributeSet::findAll(attribute::Kind kind) const { hilti::node::Set result; for ( const auto& a : attributes() ) @@ -108,7 +90,7 @@ hilti::node::Set AttributeSet::findAll(Attribute::Kind kind) const { return result; } -void AttributeSet::remove(Attribute::Kind kind) { +void AttributeSet::remove(attribute::Kind kind) { while ( const auto& a = find(kind) ) removeChild(a); } diff --git a/hilti/toolchain/src/ast/type.cc b/hilti/toolchain/src/ast/type.cc index 8c16c7602..80c1d9542 100644 --- a/hilti/toolchain/src/ast/type.cc +++ b/hilti/toolchain/src/ast/type.cc @@ -39,7 +39,7 @@ bool UnqualifiedType::isOnHeap() const { ID UnqualifiedType::cxxID() const { if ( auto decl = typeDeclaration() ) { - if ( auto a = decl->attributes()->find(hilti::Attribute::Kind::Cxxname) ) + if ( auto a = decl->attributes()->find(hilti::attribute::Kind::Cxxname) ) return ID{*a->valueAsString()}; } diff --git a/hilti/toolchain/src/compiler/codegen/codegen.cc b/hilti/toolchain/src/compiler/codegen/codegen.cc index c9e43ebf8..2457f5b3e 100644 --- a/hilti/toolchain/src/compiler/codegen/codegen.cc +++ b/hilti/toolchain/src/compiler/codegen/codegen.cc @@ -265,8 +265,8 @@ struct GlobalsVisitor : hilti::visitor::PostOrder { void operator()(declaration::Function* n) final { // TODO(robin): This method needs a refactoring. - if ( n->function()->attributes()->find(hilti::Attribute::Kind::Cxxname) && - n->function()->attributes()->find(hilti::Attribute::Kind::HavePrototype) ) + if ( n->function()->attributes()->find(hilti::attribute::Kind::Cxxname) && + n->function()->attributes()->find(hilti::attribute::Kind::HavePrototype) ) return; const auto& f = n->function(); @@ -296,7 +296,7 @@ struct GlobalsVisitor : hilti::visitor::PostOrder { auto d = cg->compile(n, ft, linkage, f->callingConvention(), f->attributes(), cid); - if ( auto a = n->function()->attributes()->find(hilti::Attribute::Kind::Cxxname) ) { + if ( auto a = n->function()->attributes()->find(hilti::attribute::Kind::Cxxname) ) { // Just add the prototype. Make sure to skip any custom namespacing. const auto& value = a->valueAsString(); if ( ! value ) { @@ -312,7 +312,7 @@ struct GlobalsVisitor : hilti::visitor::PostOrder { int64_t priority = 0; if ( is_hook && f->attributes() ) { - if ( auto x = f->attributes()->find(hilti::Attribute::Kind::Priority) ) { + if ( auto x = f->attributes()->find(hilti::attribute::Kind::Priority) ) { if ( auto i = x->valueAsInteger() ) priority = *i; else @@ -859,7 +859,7 @@ cxx::Expression CodeGen::unsignedIntegerToBitfield(type::Bitfield* t, const cxx: for ( const auto& b : t->bits(false) ) { auto x = fmt("::hilti::rt::integer::bits(%s, %d, %d, %s)", value, b->lower(), b->upper(), bitorder); - if ( auto a = b->attributes()->find(hilti::Attribute::Kind::Convert) ) { + if ( auto a = b->attributes()->find(hilti::attribute::Kind::Convert) ) { pushDollarDollar(x); bits.emplace_back(compile(*a->valueAsExpression())); popDollarDollar(); diff --git a/hilti/toolchain/src/compiler/codegen/operators.cc b/hilti/toolchain/src/compiler/codegen/operators.cc index b6ea2bb40..adb9604fd 100644 --- a/hilti/toolchain/src/compiler/codegen/operators.cc +++ b/hilti/toolchain/src/compiler/codegen/operators.cc @@ -346,7 +346,7 @@ struct Visitor : hilti::visitor::PreOrder { auto name = op0(n); - if ( auto a = f->function()->attributes()->find(hilti::Attribute::Kind::Cxxname) ) { + if ( auto a = f->function()->attributes()->find(hilti::attribute::Kind::Cxxname) ) { if ( auto s = a->valueAsString() ) name = cxx::Expression(*s); else diff --git a/hilti/toolchain/src/compiler/optimizer.cc b/hilti/toolchain/src/compiler/optimizer.cc index 454b615e7..8e48df0ba 100644 --- a/hilti/toolchain/src/compiler/optimizer.cc +++ b/hilti/toolchain/src/compiler/optimizer.cc @@ -192,7 +192,7 @@ struct FunctionVisitor : OptimizerVisitor { assert(fn.size() <= 1); // If the member declaration is marked `&always-emit` mark it as implemented. - if ( n->attributes()->has(hilti::Attribute::Kind::AlwaysEmit) ) + if ( n->attributes()->has(hilti::attribute::Kind::AlwaysEmit) ) function.defined = true; // If the member declaration includes a body mark it as implemented. @@ -203,7 +203,7 @@ struct FunctionVisitor : OptimizerVisitor { // attribute its members are defined in C++ as well. auto type_ = n->parent(); - if ( type_ && type_->attributes()->has(hilti::Attribute::Kind::Cxxname) ) + if ( type_ && type_->attributes()->has(hilti::attribute::Kind::Cxxname) ) function.defined = true; if ( n->type()->type()->as()->flavor() == type::function::Flavor::Hook ) @@ -211,7 +211,7 @@ struct FunctionVisitor : OptimizerVisitor { if ( auto type = type_ ) { for ( const auto& requirement : - n->attributes()->findAll(hilti::Attribute::Kind::NeededByFeature) ) { + n->attributes()->findAll(hilti::attribute::Kind::NeededByFeature) ) { const auto& requirement_ = requirement->valueAsString(); const auto& feature = *requirement_; @@ -275,11 +275,11 @@ struct FunctionVisitor : OptimizerVisitor { function.defined = true; // If the declaration has a `&cxxname` it is defined in C++. - else if ( fn->attributes()->has(hilti::Attribute::Kind::Cxxname) ) + else if ( fn->attributes()->has(hilti::attribute::Kind::Cxxname) ) function.defined = true; // If the member declaration is marked `&always-emit` mark it as referenced. - if ( fn->attributes()->has(hilti::Attribute::Kind::AlwaysEmit) ) + if ( fn->attributes()->has(hilti::attribute::Kind::AlwaysEmit) ) function.referenced = true; // If the function is public mark is as referenced. @@ -290,7 +290,7 @@ struct FunctionVisitor : OptimizerVisitor { // should only be emitted when certain features are active. if ( auto decl = context()->lookup(n->linkedDeclarationIndex()) ) { for ( const auto& requirement : - fn->attributes()->findAll(hilti::Attribute::Kind::NeededByFeature) ) { + fn->attributes()->findAll(hilti::attribute::Kind::NeededByFeature) ) { const auto& requirement_ = requirement->valueAsString(); const auto& feature = *requirement_; @@ -1111,7 +1111,7 @@ class FeatureRequirementsVisitor : public visitor::MutatingPreOrder { std::set reqs; for ( const auto& requirement : - parameter->attributes()->findAll(hilti::Attribute::Kind::RequiresTypeFeature) ) { + parameter->attributes()->findAll(hilti::attribute::Kind::RequiresTypeFeature) ) { auto feature = *requirement->valueAsString(); reqs.insert(std::move(feature)); } @@ -1181,7 +1181,7 @@ class FeatureRequirementsVisitor : public visitor::MutatingPreOrder { // Check if access to the field has type requirements. if ( auto type_id = type->type()->typeID() ) for ( const auto& requirement : - field->attributes()->findAll(hilti::Attribute::Kind::NeededByFeature) ) { + field->attributes()->findAll(hilti::attribute::Kind::NeededByFeature) ) { const auto feature = *requirement->valueAsString(); if ( ! ignored_features.count(type_id) || ! ignored_features.at(type_id).count(feature) ) // Enable the required feature. @@ -1213,7 +1213,7 @@ class FeatureRequirementsVisitor : public visitor::MutatingPreOrder { if ( auto type_id = type->type()->typeID() ) for ( const auto& requirement : - param->attributes()->findAll(hilti::Attribute::Kind::RequiresTypeFeature) ) { + param->attributes()->findAll(hilti::attribute::Kind::RequiresTypeFeature) ) { const auto feature = *requirement->valueAsString(); if ( ! ignored_features.count(type_id) || ! ignored_features.at(type_id).count(feature) ) { // Enable the required feature. @@ -1316,7 +1316,7 @@ class FeatureRequirementsVisitor : public visitor::MutatingPreOrder { const auto ignored_features = conditionalFeatures(x); for ( const auto& requirement : - field->attributes()->findAll(hilti::Attribute::Kind::NeededByFeature) ) { + field->attributes()->findAll(hilti::attribute::Kind::NeededByFeature) ) { const auto feature = *requirement->valueAsString(); // Enable the required feature if it is not ignored here. @@ -1339,7 +1339,7 @@ class FeatureRequirementsVisitor : public visitor::MutatingPreOrder { switch ( _stage ) { case Stage::COLLECT: { // Collect feature requirements associated with type. - for ( const auto& requirement : n->attributes()->findAll(hilti::Attribute::Kind::RequiresTypeFeature) ) + for ( const auto& requirement : n->attributes()->findAll(hilti::attribute::Kind::RequiresTypeFeature) ) _features[n->typeID()][*requirement->valueAsString()] = true; } @@ -1426,11 +1426,11 @@ struct MemberVisitor : OptimizerVisitor { return; // We never remove member marked `&always-emit`. - if ( n->attributes()->has(hilti::Attribute::Kind::AlwaysEmit) ) + if ( n->attributes()->has(hilti::attribute::Kind::AlwaysEmit) ) return; // We only remove member marked `&internal`. - if ( ! n->attributes()->find(hilti::Attribute::Kind::Internal) ) + if ( ! n->attributes()->find(hilti::attribute::Kind::Internal) ) return; auto member_id = util::join({type_id, n->id()}, "::"); @@ -1450,11 +1450,11 @@ struct MemberVisitor : OptimizerVisitor { const auto& features = _features.at(type_id); auto dependent_features = - hilti::node::transform(n->attributes()->findAll(hilti::Attribute::Kind::NeededByFeature), + hilti::node::transform(n->attributes()->findAll(hilti::attribute::Kind::NeededByFeature), [](const auto& attr) { return *attr->valueAsString(); }); for ( const auto& dependent_feature_ : - n->attributes()->findAll(hilti::Attribute::Kind::NeededByFeature) ) { + n->attributes()->findAll(hilti::attribute::Kind::NeededByFeature) ) { auto dependent_feature = *dependent_feature_->valueAsString(); // The feature flag is known and the feature is active. diff --git a/hilti/toolchain/src/compiler/parser/parser.yy b/hilti/toolchain/src/compiler/parser/parser.yy index 7503827e8..7ea842fdb 100644 --- a/hilti/toolchain/src/compiler/parser/parser.yy +++ b/hilti/toolchain/src/compiler/parser/parser.yy @@ -953,15 +953,17 @@ map_elems : map_elems ',' map_elem { $$ = std::move($1); $$.push_b map_elem : expr_no_or_error ':' expr { $$ = builder->ctorMapElement($1, $3, __loc__); } -attribute : ATTRIBUTE { if ( auto attr_kind = hilti::Attribute::tagToKind($1) ) - $$ = builder->attribute(*attr_kind, __loc__); - else - logger().error(hilti::util::fmt("invalid attribute '%s'", $1), __loc__.location()); +attribute : ATTRIBUTE { try { + $$ = builder->attribute(hilti::attribute::kind::from_string($1), __loc__); + } catch ( std::out_of_range& e ) { + error(@$, hilti::util::fmt("unknown attribute '%s'", $1)); + } } - | ATTRIBUTE '=' expr { if ( auto attr_kind = hilti::Attribute::tagToKind($1) ) - $$ = builder->attribute(*attr_kind, std::move($3), __loc__); - else - logger().error(hilti::util::fmt("invalid attribute '%s'", $1), __loc__.location()); + | ATTRIBUTE '=' expr { try { + $$ = builder->attribute(hilti::attribute::kind::from_string($1), std::move($3), __loc__); + } catch ( std::out_of_range& e ) { + error(@$, hilti::util::fmt("unknown attribute '%s'", $1)); + } } opt_attributes diff --git a/hilti/toolchain/src/compiler/printer.cc b/hilti/toolchain/src/compiler/printer.cc index 8338b96f7..51105123d 100644 --- a/hilti/toolchain/src/compiler/printer.cc +++ b/hilti/toolchain/src/compiler/printer.cc @@ -97,7 +97,7 @@ struct Printer : visitor::PreOrder { } void operator()(Attribute* n) final { - _out << n->attributeName(); + _out << to_string(n->kind()); if ( n->hasValue() ) _out << "=" << n->value(); diff --git a/hilti/toolchain/src/compiler/resolver.cc b/hilti/toolchain/src/compiler/resolver.cc index 9b94452ed..e62f076c1 100644 --- a/hilti/toolchain/src/compiler/resolver.cc +++ b/hilti/toolchain/src/compiler/resolver.cc @@ -537,11 +537,11 @@ struct VisitorPass2 : visitor::MutatingPostOrder { } void operator()(Attribute* n) final { - if ( n->kind() == hilti::Attribute::Kind::Cxxname && n->hasValue() ) { + if ( n->kind() == hilti::attribute::Kind::Cxxname && n->hasValue() ) { // Normalize values passed as `&cxxname` so they always are interpreted as FQNs by enforcing leading // `::`. if ( const auto& value = n->valueAsString(); value && ! util::startsWith(*value, "::") ) { - auto a = builder()->attribute(hilti::Attribute::Kind::Cxxname, + auto a = builder()->attribute(hilti::attribute::Kind::Cxxname, builder()->stringLiteral(util::fmt("::%s", *value))); replaceNode(n, a); } @@ -811,12 +811,12 @@ struct VisitorPass2 : visitor::MutatingPostOrder { recordChange(n, util::fmt("set linked type to %s", index)); } - if ( auto a = n->attributes()->find(hilti::Attribute::Kind::Default) ) { + if ( auto a = n->attributes()->find(hilti::attribute::Kind::Default) ) { auto val = a->valueAsExpression(); if ( auto x = coerceTo(n, *val, n->type(), false, true) ) { recordChange(*val, x, "attribute"); - n->attributes()->remove(hilti::Attribute::Kind::Default); - n->attributes()->add(context(), builder()->attribute(hilti::Attribute::Kind::Default, x)); + n->attributes()->remove(hilti::attribute::Kind::Default); + n->attributes()->add(context(), builder()->attribute(hilti::attribute::Kind::Default, x)); } } @@ -1075,9 +1075,9 @@ struct VisitorPass2 : visitor::MutatingPostOrder { } if ( auto x = n->type()->type()->tryAs(); - x && ! n->attributes()->has(hilti::Attribute::Kind::Cxxname) ) + x && ! n->attributes()->has(hilti::attribute::Kind::Cxxname) ) // Transfer the C++ name into an attribute. - n->attributes()->add(context(), builder()->attribute(hilti::Attribute::Kind::Cxxname, + n->attributes()->add(context(), builder()->attribute(hilti::attribute::Kind::Cxxname, builder()->stringLiteral(x->cxxName()))); } @@ -1582,7 +1582,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { if ( ! type::isResolved(n->itemType()) ) { auto t = n->ddType(); - if ( auto a = n->attributes()->find(hilti::Attribute::Kind::Convert) ) + if ( auto a = n->attributes()->find(hilti::attribute::Kind::Convert) ) t = (*a->valueAsExpression())->type(); if ( t->isResolved() ) { diff --git a/hilti/toolchain/src/compiler/validator.cc b/hilti/toolchain/src/compiler/validator.cc index 13fef2135..68e6380a9 100644 --- a/hilti/toolchain/src/compiler/validator.cc +++ b/hilti/toolchain/src/compiler/validator.cc @@ -65,11 +65,11 @@ using util::fmt; * attribute is added, this map must be updated to accept that attribute on any * nodes it applies to. */ -static std::unordered_map> allowed_attributes{ +static std::unordered_map> allowed_attributes{ {node::tag::Function, - {Attribute::Kind::Cxxname, Attribute::Kind::HavePrototype, Attribute::Kind::Priority, Attribute::Kind::Static, - Attribute::Kind::NeededByFeature, Attribute::Kind::Debug, Attribute::Kind::Foreach, Attribute::Kind::Error}}, - {node::tag::declaration::Parameter, {Attribute::Kind::RequiresTypeFeature}}, + {attribute::Kind::Cxxname, attribute::Kind::HavePrototype, attribute::Kind::Priority, attribute::Kind::Static, + attribute::Kind::NeededByFeature, attribute::Kind::Debug, attribute::Kind::Foreach, attribute::Kind::Error}}, + {node::tag::declaration::Parameter, {attribute::Kind::RequiresTypeFeature}}, }; void hilti::validator::VisitorMixIn::deprecated(const std::string& msg, const Location& l) const { @@ -156,7 +156,7 @@ struct VisitorPost : visitor::PreOrder, public validator::VisitorMixIn { for ( const auto& attr : attributes->attributes() ) { if ( allowed.find(attr->kind()) == allowed.end() ) - error(hilti::util::fmt("invalid attribute '%s' in %s", attr->attributeName(), where), attr); + error(hilti::util::fmt("invalid attribute '%s' in %s", to_string(attr->kind()), where), attr); } } @@ -215,7 +215,7 @@ struct VisitorPost : visitor::PreOrder, public validator::VisitorMixIn { checkNodeAttributes(n->nodeTag(), n->attributes(), "function"); if ( auto attrs = n->attributes() ) { - if ( auto prio = attrs->find(hilti::Attribute::Kind::Priority) ) { + if ( auto prio = attrs->find(hilti::attribute::Kind::Priority) ) { if ( n->ftype()->flavor() != type::function::Flavor::Hook ) error("only hooks can have priorities", n); @@ -307,7 +307,7 @@ struct VisitorPost : visitor::PreOrder, public validator::VisitorMixIn { if ( n->type()->isWildcard() ) { if ( auto d = n->parent(4)->tryAs() ) { - if ( ! d->function()->attributes()->has(hilti::Attribute::Kind::Cxxname) ) + if ( ! d->function()->attributes()->has(hilti::attribute::Kind::Cxxname) ) error(fmt("parameter '%s' cannot have wildcard type; only allowed with runtime library " "functions declared with &cxxname", n->id()), @@ -315,7 +315,7 @@ struct VisitorPost : visitor::PreOrder, public validator::VisitorMixIn { } if ( auto d = n->parent(4)->tryAs() ) { - if ( ! d->attributes()->has(hilti::Attribute::Kind::Cxxname) ) + if ( ! d->attributes()->has(hilti::attribute::Kind::Cxxname) ) error(fmt("parameter '%s' cannot have wildcard type; only allowed with methods in runtime " "library structs declared with &cxxname", n->id()), @@ -325,7 +325,7 @@ struct VisitorPost : visitor::PreOrder, public validator::VisitorMixIn { if ( auto attrs = n->attributes() ) for ( const auto& attr : attrs->attributes() ) { - if ( attr->kind() == hilti::Attribute::Kind::RequiresTypeFeature ) { + if ( attr->kind() == hilti::attribute::Kind::RequiresTypeFeature ) { if ( auto x = attr->valueAsString(); ! x ) error(x.error(), n); } @@ -392,7 +392,7 @@ struct VisitorPost : visitor::PreOrder, public validator::VisitorMixIn { void operator()(ctor::Null* n) final {} void operator()(ctor::RegExp* n) final { - if ( n->attributes()->has(hilti::Attribute::Kind::Anchor) ) + if ( n->attributes()->has(hilti::attribute::Kind::Anchor) ) // This can end up reporting the same location multiple times, // which seems fine. Otherwise we'd need to explicitly track what's // reported already. diff --git a/spicy/toolchain/include/ast/declarations/hook.h b/spicy/toolchain/include/ast/declarations/hook.h index 0b5f009e6..8a122312a 100644 --- a/spicy/toolchain/include/ast/declarations/hook.h +++ b/spicy/toolchain/include/ast/declarations/hook.h @@ -73,22 +73,22 @@ class Hook : public Declaration { auto unitFieldIndex() { return _unit_field_index; } hilti::Expression* priority() const { - if ( auto attr = attributes()->find(hilti::Attribute::Kind::Priority) ) + if ( auto attr = attributes()->find(hilti::attribute::Kind::Priority) ) return *attr->valueAsExpression(); else return nullptr; } hook::Type hookType() const { - if ( attributes()->has(hilti::Attribute::Kind::Foreach) ) + if ( attributes()->has(hilti::attribute::Kind::Foreach) ) return hook::Type::ForEach; - else if ( attributes()->has(hilti::Attribute::Kind::Error) ) + else if ( attributes()->has(hilti::attribute::Kind::Error) ) return hook::Type::Error; else return hook::Type::Standard; } - auto isDebug() const { return attributes()->has(hilti::Attribute::Kind::Debug); } + auto isDebug() const { return attributes()->has(hilti::attribute::Kind::Debug); } void setUnitTypeIndex(hilti::ast::TypeIndex index) { assert(index); diff --git a/spicy/toolchain/include/ast/types/unit-items/variable.h b/spicy/toolchain/include/ast/types/unit-items/variable.h index 10b5579c1..efaf11808 100644 --- a/spicy/toolchain/include/ast/types/unit-items/variable.h +++ b/spicy/toolchain/include/ast/types/unit-items/variable.h @@ -24,7 +24,7 @@ class Variable : public unit::Item { auto default_() const { return child(1); } auto attributes() const { return child(2); } - bool isOptional() const { return attributes()->has(hilti::Attribute::Kind::Optional); } + bool isOptional() const { return attributes()->has(hilti::attribute::Kind::Optional); } QualifiedType* itemType() const final { return child(0); } diff --git a/spicy/toolchain/include/compiler/detail/codegen/productions/skip.h b/spicy/toolchain/include/compiler/detail/codegen/productions/skip.h index 63b0964d6..4d0c4a939 100644 --- a/spicy/toolchain/include/compiler/detail/codegen/productions/skip.h +++ b/spicy/toolchain/include/compiler/detail/codegen/productions/skip.h @@ -33,7 +33,7 @@ class Skip : public Production { bool isAtomic() const final { return _ctor ? _ctor->isAtomic() : true; }; bool isEodOk() const final { - return _ctor ? _ctor->isEodOk() : _field->attributes()->has(hilti::Attribute::Kind::Eod); + return _ctor ? _ctor->isEodOk() : _field->attributes()->has(hilti::attribute::Kind::Eod); }; bool isLiteral() const final { return _ctor ? _ctor->isLiteral() : false; }; bool isNullable() const final { return _ctor ? _ctor->isNullable() : false; }; diff --git a/spicy/toolchain/src/ast/types/unit-items/field.cc b/spicy/toolchain/src/ast/types/unit-items/field.cc index 1d1151ec8..d3c9912ef 100644 --- a/spicy/toolchain/src/ast/types/unit-items/field.cc +++ b/spicy/toolchain/src/ast/types/unit-items/field.cc @@ -12,7 +12,7 @@ using namespace spicy; using namespace spicy::detail; std::optional> type::unit::item::Field::convertExpression() const { - if ( auto convert = attributes()->find(hilti::Attribute::Kind::Convert) ) + if ( auto convert = attributes()->find(hilti::attribute::Kind::Convert) ) return std::make_pair(*convert->valueAsExpression(), nullptr); auto t = parseType(); @@ -21,7 +21,7 @@ std::optional> type::unit::item::Field::c t = x->dereferencedType(); if ( auto x = t->type()->tryAs() ) { - if ( auto convert = x->attributes()->find(hilti::Attribute::Kind::Convert) ) + if ( auto convert = x->attributes()->find(hilti::attribute::Kind::Convert) ) return std::make_pair(*convert->valueAsExpression(), t); } @@ -40,9 +40,9 @@ struct SizeVisitor : hilti::visitor::PreOrder { Expression* result = nullptr; void operator()(hilti::type::Address* n) final { - if ( field.attributes()->has(hilti::Attribute::Kind::IPv4) ) + if ( field.attributes()->has(hilti::attribute::Kind::IPv4) ) result = builder->integer(4U); - else if ( field.attributes()->has(hilti::Attribute::Kind::IPv6) ) + else if ( field.attributes()->has(hilti::attribute::Kind::IPv6) ) result = builder->integer(16U); else hilti::rt::cannot_be_reached(); @@ -53,7 +53,7 @@ struct SizeVisitor : hilti::visitor::PreOrder { void operator()(hilti::type::Bitfield* n) final { result = builder->integer(n->width() / 8U); } void operator()(hilti::type::Real*) final { - auto type = *field.attributes()->find(hilti::Attribute::Kind::Type)->valueAsExpression(); + auto type = *field.attributes()->find(hilti::attribute::Kind::Type)->valueAsExpression(); result = builder->ternary(builder->equal(type, builder->id("spicy::RealType::IEEE754_Single")), builder->integer(4U), builder->integer(8U)); } @@ -62,7 +62,7 @@ struct SizeVisitor : hilti::visitor::PreOrder { Expression* spicy::type::unit::item::Field::size(ASTContext* ctx) const { Builder builder(ctx); - if ( const auto& size = attributes()->find(hilti::Attribute::Kind::Size) ) + if ( const auto& size = attributes()->find(hilti::attribute::Kind::Size) ) return *size->valueAsExpression(); if ( auto size = hilti::visitor::dispatch(SizeVisitor(&builder, *this), parseType()->type(), diff --git a/spicy/toolchain/src/compiler/codegen/codegen.cc b/spicy/toolchain/src/compiler/codegen/codegen.cc index 28c6a200e..af0b61fe1 100644 --- a/spicy/toolchain/src/compiler/codegen/codegen.cc +++ b/spicy/toolchain/src/compiler/codegen/codegen.cc @@ -75,7 +75,7 @@ struct VisitorASTInfo : public visitor::PreOrder { for ( const auto& [id, p] : unit->grammar().productions() ) { auto field = p->meta().field(); - if ( ! field || ! field->attributes()->has(hilti::Attribute::Kind::Synchronize) ) + if ( ! field || ! field->attributes()->has(hilti::attribute::Kind::Synchronize) ) continue; auto lahs = unit->grammar().lookAheadsForProduction(p); @@ -139,13 +139,13 @@ struct VisitorPass1 : public visitor::MutatingPostOrder { auto qstruct = builder()->qualifiedType(struct_, n->type()->constness()); n->setType(context(), qstruct); - n->addAttribute(context(), builder()->attribute(hilti::Attribute::Kind::OnHeap)); + n->addAttribute(context(), builder()->attribute(hilti::attribute::Kind::OnHeap)); if ( info->uses_sync_advance.find(u->typeID()) != info->uses_sync_advance.end() ) // Unit has an implementation of `%sync_advance`, so add feature // requirement for %sync_advance to the struct's type // declaration. - n->addAttribute(context(), builder()->attribute(hilti::Attribute::Kind::RequiresTypeFeature, + n->addAttribute(context(), builder()->attribute(hilti::attribute::Kind::RequiresTypeFeature, builder()->stringLiteral("uses_sync_advance"))); cg->recordTypeMapping(u, struct_); @@ -678,7 +678,7 @@ hilti::declaration::Function* CodeGen::compileHook(const type::Unit& unit, const AttributeSet* attrs = builder()->attributeSet(); if ( priority ) - attrs->add(context(), builder()->attribute(hilti::Attribute::Kind::Priority, priority)); + attrs->add(context(), builder()->attribute(hilti::attribute::Kind::Priority, priority)); auto f = builder()->function(ID(hid), ft, body, hilti::function::CallingConvention::Standard, attrs, meta); return builder()->declarationFunction(f, hilti::declaration::Linkage::Struct, meta); diff --git a/spicy/toolchain/src/compiler/codegen/grammar-builder.cc b/spicy/toolchain/src/compiler/codegen/grammar-builder.cc index fffcbc6cc..fd86b72b3 100644 --- a/spicy/toolchain/src/compiler/codegen/grammar-builder.cc +++ b/spicy/toolchain/src/compiler/codegen/grammar-builder.cc @@ -73,14 +73,14 @@ struct Visitor : public visitor::PreOrder { const auto& loc = n->location(); const auto& field = pf->currentField(); auto id = pf->cg->uniquer()->get(field->id()); - auto eod = field->attributes()->find(hilti::Attribute::Kind::Eod); - auto count = field->attributes()->find(hilti::Attribute::Kind::Count); - auto size = field->attributes()->find(hilti::Attribute::Kind::Size); - auto parse_at = field->attributes()->find(hilti::Attribute::Kind::ParseAt); - auto parse_from = field->attributes()->find(hilti::Attribute::Kind::ParseFrom); - auto until = field->attributes()->find(hilti::Attribute::Kind::Until); - auto until_including = field->attributes()->find(hilti::Attribute::Kind::UntilIncluding); - auto while_ = field->attributes()->find(hilti::Attribute::Kind::While); + auto eod = field->attributes()->find(hilti::attribute::Kind::Eod); + auto count = field->attributes()->find(hilti::attribute::Kind::Count); + auto size = field->attributes()->find(hilti::attribute::Kind::Size); + auto parse_at = field->attributes()->find(hilti::attribute::Kind::ParseAt); + auto parse_from = field->attributes()->find(hilti::attribute::Kind::ParseFrom); + auto until = field->attributes()->find(hilti::attribute::Kind::Until); + auto until_including = field->attributes()->find(hilti::attribute::Kind::UntilIncluding); + auto while_ = field->attributes()->find(hilti::attribute::Kind::While); auto repeat = field->repeatCount(); auto m = sub->meta(); @@ -164,9 +164,9 @@ struct Visitor : public visitor::PreOrder { else if ( n->parseType()->type()->isA() ) { // Bytes with fixed size already handled above. - auto eod_attr = n->attributes()->find(hilti::Attribute::Kind::Eod); - auto until_attr = n->attributes()->find(hilti::Attribute::Kind::Until); - auto until_including_attr = n->attributes()->find(hilti::Attribute::Kind::UntilIncluding); + auto eod_attr = n->attributes()->find(hilti::attribute::Kind::Eod); + auto until_attr = n->attributes()->find(hilti::attribute::Kind::Until); + auto until_including_attr = n->attributes()->find(hilti::attribute::Kind::UntilIncluding); if ( eod_attr || until_attr || until_including_attr ) skip = std::make_unique(context(), pf->cg->uniquer()->get(n->id()), n, nullptr, @@ -176,8 +176,8 @@ struct Visitor : public visitor::PreOrder { if ( n->repeatCount() ) skip.reset(); - auto convert_attr = n->attributes()->find(hilti::Attribute::Kind::Convert); - auto requires_attr = n->attributes()->find(hilti::Attribute::Kind::Requires); + auto convert_attr = n->attributes()->find(hilti::attribute::Kind::Convert); + auto requires_attr = n->attributes()->find(hilti::attribute::Kind::Requires); if ( convert_attr || requires_attr ) skip.reset(); diff --git a/spicy/toolchain/src/compiler/codegen/parser-builder.cc b/spicy/toolchain/src/compiler/codegen/parser-builder.cc index f6fb17253..4f49ee805 100644 --- a/spicy/toolchain/src/compiler/codegen/parser-builder.cc +++ b/spicy/toolchain/src/compiler/codegen/parser-builder.cc @@ -771,7 +771,7 @@ struct ProductionVisitor : public production::Visitor { if ( auto ctor_ = field->ctor(); ctor_ && ctor_->as()->isNoSub() ) needs_captures = false; - if ( field->attributes()->find(hilti::Attribute::Kind::Nosub) ) + if ( field->attributes()->find(hilti::attribute::Kind::Nosub) ) needs_captures = false; if ( needs_captures ) { @@ -781,10 +781,10 @@ struct ProductionVisitor : public production::Visitor { } } - if ( auto a = field->attributes()->find(hilti::Attribute::Kind::ParseFrom) ) + if ( auto a = field->attributes()->find(hilti::attribute::Kind::ParseFrom) ) redirectInputToBytesValue(*a->valueAsExpression()); - if ( auto a = field->attributes()->find(hilti::Attribute::Kind::ParseAt) ) + if ( auto a = field->attributes()->find(hilti::attribute::Kind::ParseAt) ) redirectInputToStreamPosition(*a->valueAsExpression()); if ( pb->options().getAuxOption("spicy.track_offsets", false) ) { @@ -804,7 +804,7 @@ struct ProductionVisitor : public production::Visitor { hilti::Constness::Const))})); } - if ( field->attributes()->find(hilti::Attribute::Kind::Try) ) + if ( field->attributes()->find(hilti::attribute::Kind::Try) ) pb->initBacktracking(); return pre_container_offset; @@ -816,11 +816,11 @@ struct ProductionVisitor : public production::Visitor { // so try to extract both of them and compute the ultimate value. Expression* length = nullptr; // Only at most one of `&max-size` and `&size` will be set. - assert(! (field->attributes()->find(hilti::Attribute::Kind::Size) && - field->attributes()->find(hilti::Attribute::Kind::MaxSize))); - if ( auto a = field->attributes()->find(hilti::Attribute::Kind::Size) ) + assert(! (field->attributes()->find(hilti::attribute::Kind::Size) && + field->attributes()->find(hilti::attribute::Kind::MaxSize))); + if ( auto a = field->attributes()->find(hilti::attribute::Kind::Size) ) length = *a->valueAsExpression(); - if ( auto a = field->attributes()->find(hilti::Attribute::Kind::MaxSize) ) + if ( auto a = field->attributes()->find(hilti::attribute::Kind::MaxSize) ) // Append a sentinel byte for `&max-size` so we can detect reads beyond the expected length. length = builder()->addTmp("max_size", builder()->typeUnsignedInteger(64), builder()->sum(*a->valueAsExpression(), builder()->integer(1U))); @@ -852,7 +852,7 @@ struct ProductionVisitor : public production::Visitor { std::pair finishFullFieldParsing(type::unit::item::Field* field) { std::pair result = {state().ncur, {}}; - if ( auto a = field->attributes()->find(hilti::Attribute::Kind::MaxSize) ) { + if ( auto a = field->attributes()->find(hilti::attribute::Kind::MaxSize) ) { assert(state().ncur); // Check that we did not read into the sentinel byte. auto cond = builder()->greaterEqual(builder()->memberCall(state().cur, "offset"), @@ -870,8 +870,8 @@ struct ProductionVisitor : public production::Visitor { result.second = state().cur; } - else if ( auto a = field->attributes()->find(hilti::Attribute::Kind::Size); - a && ! field->attributes()->find(hilti::Attribute::Kind::Eod) ) { + else if ( auto a = field->attributes()->find(hilti::attribute::Kind::Size); + a && ! field->attributes()->find(hilti::attribute::Kind::Eod) ) { assert(state().ncur); _checkSizeAmount(a, state().ncur, field); } @@ -900,7 +900,7 @@ struct ProductionVisitor : public production::Visitor { HILTI_DEBUG(spicy::logging::debug::ParserBuilder, fmt("- post-parse field: %s", field->id())); - if ( field->attributes()->find(hilti::Attribute::Kind::Try) ) + if ( field->attributes()->find(hilti::attribute::Kind::Try) ) pb->finishBacktracking(); if ( pb->options().getAuxOption("spicy.track_offsets", false) ) { @@ -921,8 +921,8 @@ struct ProductionVisitor : public production::Visitor { pb->applyConvertExpression(*field, val, destination()); } - if ( field->attributes()->find(hilti::Attribute::Kind::ParseFrom) || - field->attributes()->find(hilti::Attribute::Kind::ParseAt) ) { + if ( field->attributes()->find(hilti::attribute::Kind::ParseFrom) || + field->attributes()->find(hilti::attribute::Kind::ParseAt) ) { ncur = {}; popState(); pb->saveParsePosition(); @@ -1097,7 +1097,7 @@ struct ProductionVisitor : public production::Visitor { auto re = pb->cg()->addGlobalConstant( builder()->ctorRegExp(flattened, builder()->attributeSet( - {builder()->attribute(hilti::Attribute::Kind::Nosub)}))); + {builder()->attribute(hilti::attribute::Kind::Nosub)}))); // Create the token matcher state. builder()->addLocal(ID("ncur"), state().cur); auto ms = builder()->local("ms", builder()->memberCall(re, "token_matcher")); @@ -1486,14 +1486,14 @@ struct ProductionVisitor : public production::Visitor { std::optional preAggregate(const Production* p, AttributeSet* attributes) { builder()->addCall("hilti::debugIndent", {builder()->stringLiteral("spicy")}); - if ( const auto& a = attributes->find(hilti::Attribute::Kind::ParseFrom) ) + if ( const auto& a = attributes->find(hilti::attribute::Kind::ParseFrom) ) redirectInputToBytesValue(*a->valueAsExpression()); - if ( auto a = attributes->find(hilti::Attribute::Kind::ParseAt) ) + if ( auto a = attributes->find(hilti::attribute::Kind::ParseAt) ) redirectInputToStreamPosition(*a->valueAsExpression()); std::optional ncur; - if ( const auto& a = attributes->find(hilti::Attribute::Kind::Size) ) { + if ( const auto& a = attributes->find(hilti::attribute::Kind::Size) ) { // Limit input to the specified length. auto length = *a->valueAsExpression(); auto limited = builder()->addTmp("limited_field", builder()->memberCall(state().cur, "limit", {length})); @@ -1511,14 +1511,14 @@ struct ProductionVisitor : public production::Visitor { } void postAggregate(const Production* p, AttributeSet* attributes, std::optional ncur) { - if ( auto a = attributes->find(hilti::Attribute::Kind::Size); - a && ! attributes->find(hilti::Attribute::Kind::Eod) ) { + if ( auto a = attributes->find(hilti::attribute::Kind::Size); + a && ! attributes->find(hilti::attribute::Kind::Eod) ) { _checkSizeAmount(a, *ncur); popState(); builder()->addAssign(state().cur, *ncur); } - if ( attributes->has(hilti::Attribute::Kind::ParseFrom) || attributes->has(hilti::Attribute::Kind::ParseAt) ) + if ( attributes->has(hilti::attribute::Kind::ParseFrom) || attributes->has(hilti::attribute::Kind::ParseAt) ) popState(); builder()->addCall("hilti::debugDedent", {builder()->stringLiteral("spicy")}); @@ -1575,7 +1575,7 @@ struct ProductionVisitor : public production::Visitor { // The container element type creating this counter was marked `&synchronize`. Allow any container // element to fail parsing and be skipped. This means that if `n` elements where requested and one // element fails to parse, we will return `n-1` elements. - if ( auto f = p->body()->meta().field(); f && f->attributes()->find(hilti::Attribute::Kind::Synchronize) ) { + if ( auto f = p->body()->meta().field(); f && f->attributes()->find(hilti::attribute::Kind::Synchronize) ) { auto try_ = builder()->addTry(); pushBuilder(try_.first, [&]() { parse(); }); @@ -1670,11 +1670,11 @@ struct ProductionVisitor : public production::Visitor { // during validation. Expression* length = nullptr; // Only at most one of `&max-size` and `&size` will be set. - assert(! (p->unitType()->attributes()->find(hilti::Attribute::Kind::Size) && - p->unitType()->attributes()->find(hilti::Attribute::Kind::MaxSize))); - if ( auto a = p->unitType()->attributes()->find(hilti::Attribute::Kind::Size) ) + assert(! (p->unitType()->attributes()->find(hilti::attribute::Kind::Size) && + p->unitType()->attributes()->find(hilti::attribute::Kind::MaxSize))); + if ( auto a = p->unitType()->attributes()->find(hilti::attribute::Kind::Size) ) length = *a->valueAsExpression(); - else if ( auto a = p->unitType()->attributes()->find(hilti::Attribute::Kind::MaxSize) ) + else if ( auto a = p->unitType()->attributes()->find(hilti::attribute::Kind::MaxSize) ) // Append a sentinel byte for `&max-size` so we can detect reads beyond the expected length. length = builder()->addTmp("max_size", builder()->typeUnsignedInteger(64), builder()->sum(*a->valueAsExpression(), builder()->integer(1U))); @@ -1707,7 +1707,7 @@ struct ProductionVisitor : public production::Visitor { for ( auto candidate_counter = field_counter + 1; candidate_counter < p->fields().size(); ++candidate_counter ) if ( auto candidate = p->fields()[candidate_counter]->meta().field(); - candidate && candidate->attributes()->find(hilti::Attribute::Kind::Synchronize) ) { + candidate && candidate->attributes()->find(hilti::attribute::Kind::Synchronize) ) { sync_points.emplace_back(candidate_counter); found_sync_point = true; break; @@ -1784,7 +1784,7 @@ struct ProductionVisitor : public production::Visitor { for ( int i = 0; i < trial_loops; ++i ) finishSynchronize(); - if ( auto a = p->unitType()->attributes()->find(hilti::Attribute::Kind::MaxSize) ) { + if ( auto a = p->unitType()->attributes()->find(hilti::attribute::Kind::MaxSize) ) { // Check that we did not read into the sentinel byte. auto cond = builder()->greaterEqual(builder()->memberCall(state().cur, "offset"), builder()->memberCall(state().ncur, "offset")); @@ -1797,8 +1797,8 @@ struct ProductionVisitor : public production::Visitor { builder()->addAssign(state().cur, ncur); } - else if ( auto a = p->unitType()->attributes()->find(hilti::Attribute::Kind::Size); - a && ! p->unitType()->attributes()->find(hilti::Attribute::Kind::Eod) ) { + else if ( auto a = p->unitType()->attributes()->find(hilti::attribute::Kind::Size); + a && ! p->unitType()->attributes()->find(hilti::attribute::Kind::Eod) ) { auto ncur = state().ncur; _checkSizeAmount(a, ncur); popState(); @@ -1906,10 +1906,10 @@ struct ProductionVisitor : public production::Visitor { pb->skip(size, p->location()); else if ( p->field()->parseType()->type()->isA() ) { - auto eod_attr = p->field()->attributes()->find(hilti::Attribute::Kind::Eod); - auto until_attr = p->field()->attributes()->find(hilti::Attribute::Kind::Until); + auto eod_attr = p->field()->attributes()->find(hilti::attribute::Kind::Eod); + auto until_attr = p->field()->attributes()->find(hilti::attribute::Kind::Until); if ( ! until_attr ) - until_attr = p->field()->attributes()->find(hilti::Attribute::Kind::UntilIncluding); + until_attr = p->field()->attributes()->find(hilti::attribute::Kind::UntilIncluding); if ( eod_attr ) { builder()->addDebugMsg("spicy-verbose", "- skipping to eod"); @@ -1989,7 +1989,7 @@ struct ProductionVisitor : public production::Visitor { // for internal list synchronization (failure to parse a list element tries to synchronize at // the next possible list element). if ( auto field = p->body()->meta().field(); - field && field->attributes() && field->attributes()->find(hilti::Attribute::Kind::Synchronize) ) { + field && field->attributes() && field->attributes()->find(hilti::attribute::Kind::Synchronize) ) { auto try_ = builder()->addTry(); pushBuilder(try_.first, [&]() { parse(); }); @@ -2109,9 +2109,9 @@ void ParserBuilder::addParserMethods(hilti::type::Struct* s, type::Unit* t, bool hilti::Constness::Mutable)))}; auto attr_ext_overload = builder()->attributeSet( - {builder()->attribute(hilti::Attribute::Kind::NeededByFeature, builder()->stringLiteral("is_filter")), - builder()->attribute(hilti::Attribute::Kind::NeededByFeature, builder()->stringLiteral("supports_sinks")), - builder()->attribute(hilti::Attribute::Kind::Static)}); + {builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("is_filter")), + builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("supports_sinks")), + builder()->attribute(hilti::attribute::Kind::Static)}); auto f_ext_overload1_result = builder()->qualifiedType(builder()->typeStreamView(), hilti::Constness::Mutable); auto f_ext_overload1 = @@ -2169,7 +2169,7 @@ void ParserBuilder::addParserMethods(hilti::type::Struct* s, type::Unit* t, bool auto f_ext_context_new = builder()->function(id_ext_context_new, f_ext_context_new_result, {}, hilti::type::function::Flavor::Method, hilti::declaration::Linkage::Struct, hilti::function::CallingConvention::ExternNoSuspend, - builder()->attributeSet({builder()->attribute(hilti::Attribute::Kind::Static)}), t->meta()); + builder()->attributeSet({builder()->attribute(hilti::attribute::Kind::Static)}), t->meta()); // We only actually add the functions we just build if the unit is // publicly exposed. We still build their code in either case below @@ -2409,8 +2409,8 @@ void ParserBuilder::addParserMethods(hilti::type::Struct* s, type::Unit* t, bool "hilti::RecoverableFailure"), hilti::Constness::Const)), hilti::Constness::Mutable), - builder()->attributeSet({builder()->attribute(hilti::Attribute::Kind::AlwaysEmit), - builder()->attribute(hilti::Attribute::Kind::Internal)}))); + builder()->attributeSet({builder()->attribute(hilti::attribute::Kind::AlwaysEmit), + builder()->attribute(hilti::attribute::Kind::Internal)}))); } Builder* ParserBuilder::builder() const { return _builders.empty() ? _cg->builder() : _builders.back().get(); } @@ -2438,7 +2438,7 @@ Expression* ParserBuilder::contextNewFunction(const type::Unit& t) { void ParserBuilder::newValueForField(const production::Meta& meta, Expression* value, Expression* dd) { const auto& field = meta.field(); - for ( const auto& a : field->attributes()->findAll(hilti::Attribute::Kind::Requires) ) { + for ( const auto& a : field->attributes()->findAll(hilti::attribute::Kind::Requires) ) { // We evaluate "&requires" here so that the field's value has been // set already, and is hence accessible to the condition through // "self.". @@ -2516,7 +2516,7 @@ Expression* ParserBuilder::newContainerItem(const type::unit::item::Field* field }; auto check_requires = [&]() { - for ( const auto& a : field->attributes()->findAll(hilti::Attribute::Kind::Requires) ) { + for ( const auto& a : field->attributes()->findAll(hilti::attribute::Kind::Requires) ) { pushBuilder(builder()->addBlock(), [&]() { builder()->addLocal("__dd", item); auto cond = builder()->addTmp("requires", *a->valueAsExpression()); @@ -2526,21 +2526,21 @@ Expression* ParserBuilder::newContainerItem(const type::unit::item::Field* field } }; - if ( auto a = container->attributes()->find(hilti::Attribute::Kind::Until) ) { + if ( auto a = container->attributes()->find(hilti::attribute::Kind::Until) ) { eval_condition(*a->valueAsExpression()); check_requires(); run_hook(); push_element(); } - else if ( auto a = container->attributes()->find(hilti::Attribute::Kind::UntilIncluding) ) { + else if ( auto a = container->attributes()->find(hilti::attribute::Kind::UntilIncluding) ) { check_requires(); run_hook(); push_element(); eval_condition(*a->valueAsExpression()); } - else if ( auto a = container->attributes()->find(hilti::Attribute::Kind::While) ) { + else if ( auto a = container->attributes()->find(hilti::attribute::Kind::While) ) { eval_condition(builder()->not_(*a->valueAsExpression())); check_requires(); run_hook(); @@ -2611,7 +2611,7 @@ void ParserBuilder::finalizeUnit(bool success, const Location& l) { // We evaluate any "&requires" before running the final "%done" hook // so that (1) that one can rely on the condition, and (2) we keep // running either "%done" or "%error". - for ( const auto& attr : unit->attributes()->findAll(hilti::Attribute::Kind::Requires) ) { + for ( const auto& attr : unit->attributes()->findAll(hilti::attribute::Kind::Requires) ) { auto cond = builder()->addTmp("requires", *attr->valueAsExpression()); pushBuilder(builder()->addIf(builder()->not_(cond)), [&]() { parseError(builder()->memberCall(cond, "error"), attr->value()->meta()); }); @@ -2663,11 +2663,11 @@ hilti::Attributes ParserBuilder::removeGenericParseAttributes(hilti::AttributeSe // really have a well-defined list of attributes that are clearly generic // vs field-specific. So this best-effort weeding out attributes that // field-specific code usually doesn't need to care about. - static std::unordered_set generic_attributes = { - hilti::Attribute::Kind::Convert, hilti::Attribute::Kind::Default, hilti::Attribute::Kind::Eod, - hilti::Attribute::Kind::MaxSize, hilti::Attribute::Kind::Optional, hilti::Attribute::Kind::ParseAt, - hilti::Attribute::Kind::ParseFrom, hilti::Attribute::Kind::Requires, hilti::Attribute::Kind::Size, - hilti::Attribute::Kind::Synchronize, hilti::Attribute::Kind::Try, + static std::unordered_set generic_attributes = { + hilti::attribute::Kind::Convert, hilti::attribute::Kind::Default, hilti::attribute::Kind::Eod, + hilti::attribute::Kind::MaxSize, hilti::attribute::Kind::Optional, hilti::attribute::Kind::ParseAt, + hilti::attribute::Kind::ParseFrom, hilti::attribute::Kind::Requires, hilti::attribute::Kind::Size, + hilti::attribute::Kind::Synchronize, hilti::attribute::Kind::Try, }; hilti::Attributes filtered; diff --git a/spicy/toolchain/src/compiler/codegen/parsers/literals.cc b/spicy/toolchain/src/compiler/codegen/parsers/literals.cc index 91823293e..e624aad59 100644 --- a/spicy/toolchain/src/compiler/codegen/parsers/literals.cc +++ b/spicy/toolchain/src/compiler/codegen/parsers/literals.cc @@ -60,7 +60,7 @@ struct Visitor : public visitor::PreOrder { bool needs_check = false; if ( auto field = lp->production->meta().field(); - field && field->attributes()->find(hilti::Attribute::Kind::Synchronize) ) + field && field->attributes()->find(hilti::attribute::Kind::Synchronize) ) needs_check = true; else { auto tokens = pb()->cg()->astInfo().look_aheads_in_use; @@ -144,7 +144,7 @@ struct Visitor : public visitor::PreOrder { auto attrs = builder()->attributeSet(); if ( ! state().captures ) - attrs->add(context(), builder()->attribute(hilti::Attribute::Kind::Nosub)); + attrs->add(context(), builder()->attribute(hilti::attribute::Kind::Nosub)); auto re = pb()->cg()->addGlobalConstant(builder()->ctorRegExp(n->value(), attrs)); diff --git a/spicy/toolchain/src/compiler/codegen/parsers/types.cc b/spicy/toolchain/src/compiler/codegen/parsers/types.cc index faf27d2a0..b09325ca3 100644 --- a/spicy/toolchain/src/compiler/codegen/parsers/types.cc +++ b/spicy/toolchain/src/compiler/codegen/parsers/types.cc @@ -85,10 +85,10 @@ struct TypeParser { Expression* fieldByteOrder() { Expression* byte_order = nullptr; - if ( const auto& a = meta.field()->attributes()->find(hilti::Attribute::Kind::ByteOrder) ) + if ( const auto& a = meta.field()->attributes()->find(hilti::attribute::Kind::ByteOrder) ) byte_order = *a->valueAsExpression(); - else if ( const auto& a = state().unit->attributes()->find(hilti::Attribute::Kind::ByteOrder) ) + else if ( const auto& a = state().unit->attributes()->find(hilti::attribute::Kind::ByteOrder) ) byte_order = *a->valueAsExpression(); else if ( const auto& p = state().unit->propertyItem("%byte-order") ) @@ -122,8 +122,8 @@ struct Visitor : public visitor::PreOrder { void operator()(hilti::type::Address* n) final { switch ( tp->mode ) { case TypesMode::Default: { - auto v4 = tp->meta.field()->attributes()->find(hilti::Attribute::Kind::IPv4); - auto v6 = tp->meta.field()->attributes()->find(hilti::Attribute::Kind::IPv6); + auto v4 = tp->meta.field()->attributes()->find(hilti::attribute::Kind::IPv4); + auto v6 = tp->meta.field()->attributes()->find(hilti::attribute::Kind::IPv6); (void)v6; assert(! (v4 && v6)); @@ -159,7 +159,7 @@ struct Visitor : public visitor::PreOrder { Expression* bitorder = builder()->id("hilti::BitOrder::LSB0"); if ( auto attrs = n->attributes() ) { - if ( auto a = attrs->find(hilti::Attribute::Kind::BitOrder) ) + if ( auto a = attrs->find(hilti::attribute::Kind::BitOrder) ) bitorder = *a->valueAsExpression(); } @@ -199,7 +199,7 @@ struct Visitor : public visitor::PreOrder { void operator()(hilti::type::Real* n) final { switch ( tp->mode ) { case TypesMode::Default: { - auto type = tp->meta.field()->attributes()->find(hilti::Attribute::Kind::Type); + auto type = tp->meta.field()->attributes()->find(hilti::attribute::Kind::Type); assert(type); result = tp->performUnpack(tp->destination(n), builder()->typeReal(), 4, {state().cur, *type->valueAsExpression(), tp->fieldByteOrder()}, n->meta(), @@ -271,17 +271,17 @@ struct Visitor : public visitor::PreOrder { void operator()(hilti::type::Bytes* n) final { auto attrs = tp->meta.field()->attributes(); - auto chunked_attr = attrs->find(hilti::Attribute::Kind::Chunked); - auto eod_attr = attrs->find(hilti::Attribute::Kind::Eod); - auto size_attr = attrs->find(hilti::Attribute::Kind::Size); - auto until_attr = attrs->find(hilti::Attribute::Kind::Until); - auto until_including_attr = attrs->find(hilti::Attribute::Kind::UntilIncluding); + auto chunked_attr = attrs->find(hilti::attribute::Kind::Chunked); + auto eod_attr = attrs->find(hilti::attribute::Kind::Eod); + auto size_attr = attrs->find(hilti::attribute::Kind::Size); + auto until_attr = attrs->find(hilti::attribute::Kind::Until); + auto until_including_attr = attrs->find(hilti::attribute::Kind::UntilIncluding); bool to_eod = (eod_attr != nullptr); // parse to end of input data bool parse_attr = false; // do we have a &parse-* attribute - if ( (tp->meta.field()->attributes()->find(hilti::Attribute::Kind::ParseFrom) || - tp->meta.field()->attributes()->find(hilti::Attribute::Kind::ParseAt)) && + if ( (tp->meta.field()->attributes()->find(hilti::attribute::Kind::ParseFrom) || + tp->meta.field()->attributes()->find(hilti::attribute::Kind::ParseAt)) && ! (until_attr || until_including_attr) ) parse_attr = true; diff --git a/spicy/toolchain/src/compiler/codegen/unit-builder.cc b/spicy/toolchain/src/compiler/codegen/unit-builder.cc index 3fbf34780..a1e74426f 100644 --- a/spicy/toolchain/src/compiler/codegen/unit-builder.cc +++ b/spicy/toolchain/src/compiler/codegen/unit-builder.cc @@ -44,20 +44,20 @@ struct FieldBuilder : public visitor::PreOrder { void operator()(spicy::type::unit::item::Field* f) final { // Create struct field. - auto attrs = builder()->attributeSet({builder()->attribute(hilti::Attribute::Kind::Optional)}); + auto attrs = builder()->attributeSet({builder()->attribute(hilti::attribute::Kind::Optional)}); - if ( auto x = f->attributes()->find(hilti::Attribute::Kind::Default) ) + if ( auto x = f->attributes()->find(hilti::attribute::Kind::Default) ) attrs->add(context(), x); if ( f->isAnonymous() ) - attrs->add(context(), builder()->attribute(hilti::Attribute::Kind::Anonymous)); + attrs->add(context(), builder()->attribute(hilti::attribute::Kind::Anonymous)); if ( (f->isAnonymous() || f->isSkip() || f->parseType()->type()->isA()) && ! f->itemType()->type()->isA() ) // This field will never make it into the C++ struct. We still // carry it around though as that makes type inference easier at // times, and also can improve error messages. - attrs->add(context(), builder()->attribute(hilti::Attribute::Kind::NoEmit)); + attrs->add(context(), builder()->attribute(hilti::attribute::Kind::NoEmit)); auto nf = builder()->declarationField(f->id(), f->itemType(), attrs, f->meta()); addField(nf); @@ -126,10 +126,10 @@ struct FieldBuilder : public visitor::PreOrder { // Create struct field. if ( auto x = f->default_() ) - attrs->add(context(), builder()->attribute(hilti::Attribute::Kind::Default, x)); + attrs->add(context(), builder()->attribute(hilti::attribute::Kind::Default, x)); if ( f->isOptional() ) - attrs->add(context(), builder()->attribute(hilti::Attribute::Kind::Optional)); + attrs->add(context(), builder()->attribute(hilti::attribute::Kind::Optional)); auto nf = builder()->declarationField(f->id(), ftype, attrs, f->meta()); addField(nf); @@ -138,9 +138,9 @@ struct FieldBuilder : public visitor::PreOrder { void operator()(spicy::type::unit::item::Sink* s) final { auto type = builder()->typeName("spicy_rt::Sink", s->meta()); auto attrs = - builder()->attributeSet({builder()->attribute(hilti::Attribute::Kind::Default, builder()->new_(type)), - builder()->attribute(hilti::Attribute::Kind::Internal), - builder()->attribute(hilti::Attribute::Kind::NeededByFeature, + builder()->attributeSet({builder()->attribute(hilti::attribute::Kind::Default, builder()->new_(type)), + builder()->attribute(hilti::attribute::Kind::Internal), + builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("supports_sinks"))}); auto sink = builder()->qualifiedType(builder()->typeSink(), hilti::Constness::Mutable, hilti::Side::LHS); @@ -186,12 +186,12 @@ UnqualifiedType* CodeGen::compileUnit(type::Unit* unit, bool declare_only) { v.addField(builder()->declarationField(ID("__offsets"), vec, builder()->attributeSet( - {builder()->attribute(hilti::Attribute::Kind::Internal), - builder()->attribute(hilti::Attribute::Kind::AlwaysEmit)}))); + {builder()->attribute(hilti::attribute::Kind::Internal), + builder()->attribute(hilti::attribute::Kind::AlwaysEmit)}))); } if ( auto context = unit->contextType() ) { - auto attrs = builder()->attributeSet({builder()->attribute(hilti::Attribute::Kind::Internal)}); + auto attrs = builder()->attributeSet({builder()->attribute(hilti::attribute::Kind::Internal)}); auto ftype = builder()->typeStrongReference(builder()->qualifiedType(context, hilti::Constness::Mutable)); auto f = builder()->declarationField(ID("__context"), builder()->qualifiedType(ftype, hilti::Constness::Mutable), @@ -206,7 +206,7 @@ UnqualifiedType* CodeGen::compileUnit(type::Unit* unit, bool declare_only) { add_hook("0x25_finally", {}); auto attr_sync = builder()->attributeSet( - {builder()->attribute(hilti::Attribute::Kind::NeededByFeature, builder()->stringLiteral("synchronization"))}); + {builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("synchronization"))}); add_hook("0x25_confirmed", {}, attr_sync); add_hook("0x25_rejected", {}, attr_sync); add_hook("0x25_synced", {}, attr_sync); @@ -235,7 +235,7 @@ UnqualifiedType* CodeGen::compileUnit(type::Unit* unit, bool declare_only) { builder()->parameter("data", builder()->typeBytes())}); auto attr_uses_stream = - builder()->attribute(hilti::Attribute::Kind::NeededByFeature, builder()->stringLiteral("uses_stream")); + builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("uses_stream")); auto stream = builder()->declarationField(ID("__stream"), builder()->qualifiedType(builder()->typeWeakReference( @@ -243,57 +243,57 @@ UnqualifiedType* CodeGen::compileUnit(type::Unit* unit, bool declare_only) { hilti::Constness::Const)), hilti::Constness::Const), builder()->attributeSet( - {builder()->attribute(hilti::Attribute::Kind::Internal), attr_uses_stream})); + {builder()->attribute(hilti::attribute::Kind::Internal), attr_uses_stream})); v.addField(stream); auto attr_sync_advance = builder()->attributeSet( - {builder()->attribute(hilti::Attribute::Kind::NeededByFeature, builder()->stringLiteral("uses_sync_advance"))}); + {builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("uses_sync_advance"))}); add_hook("0x25_sync_advance", {builder()->parameter("offset", builder()->typeUnsignedInteger(64))}, attr_sync_advance); // Fields related to random-access functionality. auto attr_uses_random_access = - builder()->attribute(hilti::Attribute::Kind::NeededByFeature, builder()->stringLiteral("uses_random_access")); + builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("uses_random_access")); auto iter = builder()->qualifiedType(builder()->typeStreamIterator(), hilti::Constness::Mutable); auto f1 = builder()->declarationField(ID("__begin"), iter, - builder()->attributeSet({builder()->attribute(hilti::Attribute::Kind::Internal), + builder()->attributeSet({builder()->attribute(hilti::attribute::Kind::Internal), attr_uses_random_access})); auto f2 = builder()->declarationField(ID("__position_update"), builder()->qualifiedType(builder()->typeOptional(iter), hilti::Constness::Mutable), - builder()->attributeSet({builder()->attribute(hilti::Attribute::Kind::Internal), + builder()->attributeSet({builder()->attribute(hilti::attribute::Kind::Internal), attr_uses_random_access})); v.addField(f1); v.addField(f2); // Fields related to offset functionality. auto attr_uses_offset = - builder()->attribute(hilti::Attribute::Kind::NeededByFeature, builder()->stringLiteral("uses_offset")); + builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("uses_offset")); auto f3 = builder()->declarationField(ID("__offset"), builder()->qualifiedType(builder()->typeUnsignedInteger(64), hilti::Constness::Mutable), builder()->attributeSet( - {builder()->attribute(hilti::Attribute::Kind::Internal), attr_uses_offset})); + {builder()->attribute(hilti::attribute::Kind::Internal), attr_uses_offset})); v.addField(f3); { - auto attrs = builder()->attributeSet({builder()->attribute(hilti::Attribute::Kind::Static), - builder()->attribute(hilti::Attribute::Kind::Internal), - builder()->attribute(hilti::Attribute::Kind::NeededByFeature, + auto attrs = builder()->attributeSet({builder()->attribute(hilti::attribute::Kind::Static), + builder()->attribute(hilti::attribute::Kind::Internal), + builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("supports_filters"))}); if ( unit->isPublic() ) - attrs->add(context(), builder()->attribute(hilti::Attribute::Kind::AlwaysEmit)); + attrs->add(context(), builder()->attribute(hilti::attribute::Kind::AlwaysEmit)); else - attrs->add(context(), builder()->attribute(hilti::Attribute::Kind::NeededByFeature, + attrs->add(context(), builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("supports_sinks"))); if ( unit->isFilter() ) - attrs->add(context(), builder()->attribute(hilti::Attribute::Kind::NeededByFeature, + attrs->add(context(), builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("is_filter"))); auto parser = builder()->declarationField(ID("__parser"), @@ -305,15 +305,15 @@ UnqualifiedType* CodeGen::compileUnit(type::Unit* unit, bool declare_only) { } { - auto attrs = builder()->attributeSet({builder()->attribute(hilti::Attribute::Kind::Internal), - builder()->attribute(hilti::Attribute::Kind::NeededByFeature, + auto attrs = builder()->attributeSet({builder()->attribute(hilti::attribute::Kind::Internal), + builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("supports_sinks"))}); // If the unit has a `%mime-type` property consumers can connect to it via // MIME type with `connect_mime_type`. In that case we need to always emit // the field since we cannot detect use of this type later on. if ( unit->propertyItem("%mime-type") ) - attrs->add(context(), builder()->attribute(hilti::Attribute::Kind::AlwaysEmit)); + attrs->add(context(), builder()->attribute(hilti::attribute::Kind::AlwaysEmit)); auto sink = builder()->declarationField(ID("__sink"), builder()->qualifiedType(builder()->typeName("spicy_rt::SinkState"), @@ -332,8 +332,8 @@ UnqualifiedType* CodeGen::compileUnit(type::Unit* unit, bool declare_only) { hilti::Constness::Mutable)), hilti::Constness::Mutable), builder()->attributeSet( - {builder()->attribute(hilti::Attribute::Kind::Internal), - builder()->attribute(hilti::Attribute::Kind::NeededByFeature, + {builder()->attribute(hilti::attribute::Kind::Internal), + builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("supports_filters"))})); v.addField(filters); } @@ -348,8 +348,8 @@ UnqualifiedType* CodeGen::compileUnit(type::Unit* unit, bool declare_only) { hilti::Constness::Mutable)), hilti::Constness::Mutable), builder()->attributeSet( - {builder()->attribute(hilti::Attribute::Kind::Internal), - builder()->attribute(hilti::Attribute::Kind::NeededByFeature, + {builder()->attribute(hilti::attribute::Kind::Internal), + builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("is_filter"))})); v.addField(forward); } @@ -358,7 +358,7 @@ UnqualifiedType* CodeGen::compileUnit(type::Unit* unit, bool declare_only) { v.addField( builder()->declarationField(ID("__parse_stage1"), builder()->qualifiedType(ft, hilti::Constness::Mutable), {})); - if ( auto convert = unit->attributes()->find(hilti::Attribute::Kind::Convert) ) { + if ( auto convert = unit->attributes()->find(hilti::attribute::Kind::Convert) ) { auto expression = *convert->valueAsExpression(); auto result = builder()->qualifiedType(builder()->typeAuto(), hilti::Constness::Mutable); auto ftype = builder()->typeFunction(result, {}, hilti::type::function::Flavor::Method, expression->meta()); @@ -385,8 +385,8 @@ UnqualifiedType* CodeGen::compileUnit(type::Unit* unit, bool declare_only) { void CodeGen::compilePublicUnitAlias(hilti::declaration::Module* module, const ID& alias_id, type::Unit* unit) { // We create a mini parser struct here that just contains the `__parser` field for runtime registration. auto attrs = builder()->attributeSet( - {builder()->attribute(hilti::Attribute::Kind::Static), builder()->attribute(hilti::Attribute::Kind::Internal), - builder()->attribute(hilti::Attribute::Kind::NeededByFeature, builder()->stringLiteral("supports_filters"))}); + {builder()->attribute(hilti::attribute::Kind::Static), builder()->attribute(hilti::attribute::Kind::Internal), + builder()->attribute(hilti::attribute::Kind::NeededByFeature, builder()->stringLiteral("supports_filters"))}); auto parser_field = builder()->declarationField(ID("__parser"), builder()->qualifiedType(builder()->typeName("spicy_rt::Parser"), @@ -411,8 +411,8 @@ void CodeGen::_compileParserRegistration(const ID& public_id, const ID& struct_i auto dir = ID("spicy_rt::Direction::Both"); if ( const auto& attrs = p->attributes() ) { - auto orig = attrs->find(hilti::Attribute::Kind::Originator); - auto resp = attrs->find(hilti::Attribute::Kind::Responder); + auto orig = attrs->find(hilti::attribute::Kind::Originator); + auto resp = attrs->find(hilti::attribute::Kind::Responder); if ( orig && ! resp ) dir = ID("spicy_rt::Direction::Originator"); diff --git a/spicy/toolchain/src/compiler/parser/parser.yy b/spicy/toolchain/src/compiler/parser/parser.yy index aeaf137b7..d615f707e 100644 --- a/spicy/toolchain/src/compiler/parser/parser.yy +++ b/spicy/toolchain/src/compiler/parser/parser.yy @@ -910,17 +910,19 @@ unit_hook_id: { driver->enableHookIDMode(); } { driver->disableHookIDMode(); } { $$ = hilti::ID(hilti::util::replace($2, "%", "0x25_")); } unit_hook_attribute - : FOREACH { $$ = builder->attribute(hilti::Attribute::Kind::Foreach, __loc__); } - | PRIORITY '=' expr { $$ = builder->attribute(hilti::Attribute::Kind::Priority, std::move($3), __loc__); } - | PROPERTY { if ( auto attr_kind = hilti::Attribute::tagToKind($1) ) - $$ = builder->attribute(*attr_kind, __loc__); - else - hilti::logger().error(hilti::util::fmt("invalid attribute '%s'", $1), __loc__.location()); + : FOREACH { $$ = builder->attribute(hilti::attribute::Kind::Foreach, __loc__); } + | PRIORITY '=' expr { $$ = builder->attribute(hilti::attribute::Kind::Priority, std::move($3), __loc__); } + | PROPERTY { try { + $$ = builder->attribute(hilti::attribute::kind::from_string($1), __loc__); + } catch ( std::out_of_range& e ) { + error(@$, hilti::util::fmt("unknown attribute '%s'", $1)); + } } - | ATTRIBUTE { if ( auto attr_kind = hilti::Attribute::tagToKind($1) ) - $$ = builder->attribute(*attr_kind, __loc__); - else - hilti::logger().error(hilti::util::fmt("invalid attribute '%s'", $1), __loc__.location()); + | ATTRIBUTE { try { + $$ = builder->attribute(hilti::attribute::kind::from_string($1), __loc__); + } catch ( std::out_of_range& e ) { + error(@$, hilti::util::fmt("unknown attribute '%s'", $1)); + } } unit_switch : SWITCH opt_unit_switch_expr '{' unit_switch_cases '}' opt_attributes opt_unit_field_condition ';' @@ -1187,19 +1189,17 @@ map_elem : expr_no_or_error ':' expr { $$ = builder->ctorMapElement( /* Attributes */ -attribute : ATTRIBUTE { if ( auto attr_kind = hilti::Attribute::tagToKind($1) ) - $$ = builder->attribute(*attr_kind, __loc__); - else { - hilti::logger().error(hilti::util::fmt("invalid attribute '%s'", $1), __loc__.location()); - $$ = {}; - } +attribute : ATTRIBUTE { try { + $$ = builder->attribute(hilti::attribute::kind::from_string($1), __loc__); + } catch ( std::out_of_range& e ) { + error(@$, hilti::util::fmt("unknown attribute '%s'", $1)); + } } - | ATTRIBUTE '=' expr { if ( auto attr_kind = hilti::Attribute::tagToKind($1) ) - $$ = builder->attribute(*attr_kind, std::move($3), __loc__); - else { - hilti::logger().error(hilti::util::fmt("invalid attribute '%s'", $1), __loc__.location()); - $$ = {}; - } + | ATTRIBUTE '=' expr { try { + $$ = builder->attribute(hilti::attribute::kind::from_string($1), std::move($3), __loc__); + } catch ( std::out_of_range& e ) { + error(@$, hilti::util::fmt("unknown attribute '%s'", $1)); + } } opt_attributes diff --git a/spicy/toolchain/src/compiler/resolver.cc b/spicy/toolchain/src/compiler/resolver.cc index 3e6d8dda6..19fa5d0de 100644 --- a/spicy/toolchain/src/compiler/resolver.cc +++ b/spicy/toolchain/src/compiler/resolver.cc @@ -115,7 +115,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { } void operator()(hilti::Attribute* n) final { - if ( n->kind() == hilti::Attribute::Kind::Size || n->kind() == hilti::Attribute::Kind::MaxSize ) { + if ( n->kind() == hilti::attribute::Kind::Size || n->kind() == hilti::attribute::Kind::MaxSize ) { if ( ! n->hasValue() ) // Caught elsewhere, we don't want to report it here again. return; @@ -123,13 +123,13 @@ struct VisitorPass2 : visitor::MutatingPostOrder { if ( auto x = n->coerceValueTo(builder(), builder()->qualifiedType(builder()->typeUnsignedInteger(64), hilti::Constness::Const)) ) { if ( *x ) - recordChange(n, std::string{n->attributeName()}); + recordChange(n, to_string(n->kind())); } else n->addError(x.error()); } - else if ( n->kind() == hilti::Attribute::Kind::Requires ) { + else if ( n->kind() == hilti::attribute::Kind::Requires ) { if ( ! n->hasValue() ) // Caught elsewhere, we don't want to report it here again. return; @@ -153,7 +153,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { auto new_cond = builder()->conditionTest(*ne.coerced, builder()->expression(builder()->ctorError(msg)), cond->meta()); n->replaceChild(context(), cond, new_cond); - recordChange(n, std::string(hilti::Attribute::kindToString(n->kind()))); + recordChange(n, std::string(to_string(n->kind()))); } } @@ -345,7 +345,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { if ( ! attr ) continue; - if ( attr->kind() != hilti::Attribute::Kind::Convert ) + if ( attr->kind() != hilti::attribute::Kind::Convert ) return; // The direct parent of the attribute set containing the attribute should be the unit. @@ -447,8 +447,8 @@ struct VisitorPass2 : visitor::MutatingPostOrder { void operator()(hilti::type::Bitfield* n) final { if ( auto field = n->parent(2)->tryAs() ) { // Transfer any "&bitorder" attribute over to the type. - if ( auto a = field->attributes()->find(hilti::Attribute::Kind::BitOrder); - a && ! n->attributes()->find(hilti::Attribute::Kind::BitOrder) ) { + if ( auto a = field->attributes()->find(hilti::attribute::Kind::BitOrder); + a && ! n->attributes()->find(hilti::attribute::Kind::BitOrder) ) { recordChange(n, "transfer &bitorder attribute"); n->attributes()->add(context(), a); } @@ -456,8 +456,8 @@ struct VisitorPass2 : visitor::MutatingPostOrder { if ( auto decl = n->parent(2)->tryAs() ) { // Transfer any "&bitorder" attribute over to the type. - if ( auto a = decl->attributes()->find(hilti::Attribute::Kind::BitOrder); - a && ! n->attributes()->find(hilti::Attribute::Kind::BitOrder) ) { + if ( auto a = decl->attributes()->find(hilti::attribute::Kind::BitOrder); + a && ! n->attributes()->find(hilti::attribute::Kind::BitOrder) ) { recordChange(n, "transfer &bitorder attribute"); n->attributes()->add(context(), a); } @@ -536,7 +536,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { if ( x->second ) { // Unit-level convert on the sub-item. auto u = x->second->type()->as(); - auto a = u->attributes()->find(hilti::Attribute::Kind::Convert); + auto a = u->attributes()->find(hilti::attribute::Kind::Convert); assert(a); auto e = *a->valueAsExpression(); if ( e->isResolved() ) @@ -591,7 +591,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { size_t ok_attrs = 0; const auto& attrs = n->attributes()->attributes(); for ( const auto& a : attrs ) { - if ( a->kind() == hilti::Attribute::Kind::Requires ) + if ( a->kind() == hilti::attribute::Kind::Requires ) ok_attrs++; } @@ -620,7 +620,7 @@ struct VisitorPass2 : visitor::MutatingPostOrder { // subitem so that we have our recursive machinery available // (which we don't have for pure types). if ( auto unit_type = t->type()->type()->tryAs(); - unit_type && unit_type->attributes()->has(hilti::Attribute::Kind::Convert) ) { + unit_type && unit_type->attributes()->has(hilti::attribute::Kind::Convert) ) { auto inner_field = builder()->typeUnitItemField({}, tt, false, n->arguments(), {}, {}, {}, {}, {}, n->meta()); inner_field->setIndex(*n->index()); diff --git a/spicy/toolchain/src/compiler/scope-builder.cc b/spicy/toolchain/src/compiler/scope-builder.cc index c3e4d165d..b13f5fa58 100644 --- a/spicy/toolchain/src/compiler/scope-builder.cc +++ b/spicy/toolchain/src/compiler/scope-builder.cc @@ -69,9 +69,9 @@ struct VisitorScopeBuilder : visitor::PostOrder { } void operator()(hilti::Attribute* n) final { - if ( hilti::Attribute::isOneOf(n->kind(), - {hilti::Attribute::Kind::Until, hilti::Attribute::Kind::UntilIncluding, - hilti::Attribute::Kind::While}) ) { + if ( hilti::attribute::isOneOf(n->kind(), + {hilti::attribute::Kind::Until, hilti::attribute::Kind::UntilIncluding, + hilti::attribute::Kind::While}) ) { auto f = n->parent(); if ( ! (f && f->isContainer()) ) return; diff --git a/spicy/toolchain/src/compiler/validator.cc b/spicy/toolchain/src/compiler/validator.cc index 0370fe39c..76f53734d 100644 --- a/spicy/toolchain/src/compiler/validator.cc +++ b/spicy/toolchain/src/compiler/validator.cc @@ -31,53 +31,52 @@ namespace { * This also includes many types that cannot themselves contain attributes. Those * types ensure that they can be within a field with the provided attributes. */ -std::unordered_map> allowed_attributes{ +std::unordered_map> allowed_attributes{ {hilti::node::tag::declaration::Hook, - {hilti::Attribute::Kind::Foreach, hilti::Attribute::Kind::Error, hilti::Attribute::Kind::Debug, - hilti::Attribute::Kind::Priority}}, - {hilti::node::tag::declaration::Type, {hilti::Attribute::Kind::Cxxname, hilti::Attribute::Kind::BitOrder}}, - {hilti::node::tag::type::Enum, {hilti::Attribute::Kind::Cxxname}}, + {hilti::attribute::Kind::Foreach, hilti::attribute::Kind::Error, hilti::attribute::Kind::Debug, + hilti::attribute::Kind::Priority}}, + {hilti::node::tag::declaration::Type, {hilti::attribute::Kind::Cxxname, hilti::attribute::Kind::BitOrder}}, + {hilti::node::tag::type::Enum, {hilti::attribute::Kind::Cxxname}}, {hilti::node::tag::type::Unit, - {hilti::Attribute::Kind::ByteOrder, hilti::Attribute::Kind::Convert, hilti::Attribute::Kind::Size, - hilti::Attribute::Kind::MaxSize, hilti::Attribute::Kind::Requires}}, - {hilti::node::tag::type::unit::item::Variable, {hilti::Attribute::Kind::Optional}}, + {hilti::attribute::Kind::ByteOrder, hilti::attribute::Kind::Convert, hilti::attribute::Kind::Size, + hilti::attribute::Kind::MaxSize, hilti::attribute::Kind::Requires}}, + {hilti::node::tag::type::unit::item::Variable, {hilti::attribute::Kind::Optional}}, {hilti::node::tag::type::unit::item::Field, - {hilti::Attribute::Kind::Count, hilti::Attribute::Kind::Convert, hilti::Attribute::Kind::Chunked, - hilti::Attribute::Kind::Synchronize, hilti::Attribute::Kind::Size, hilti::Attribute::Kind::ParseAt, - hilti::Attribute::Kind::MaxSize, hilti::Attribute::Kind::ParseFrom, hilti::Attribute::Kind::Type, - hilti::Attribute::Kind::Until, hilti::Attribute::Kind::UntilIncluding, hilti::Attribute::Kind::While, - hilti::Attribute::Kind::IPv4, hilti::Attribute::Kind::IPv6, hilti::Attribute::Kind::Eod, - hilti::Attribute::Kind::ByteOrder, hilti::Attribute::Kind::BitOrder, hilti::Attribute::Kind::Requires, - hilti::Attribute::Kind::Try, hilti::Attribute::Kind::Nosub, hilti::Attribute::Kind::Default}}, + {hilti::attribute::Kind::Count, hilti::attribute::Kind::Convert, hilti::attribute::Kind::Chunked, + hilti::attribute::Kind::Synchronize, hilti::attribute::Kind::Size, hilti::attribute::Kind::ParseAt, + hilti::attribute::Kind::MaxSize, hilti::attribute::Kind::ParseFrom, hilti::attribute::Kind::Type, + hilti::attribute::Kind::Until, hilti::attribute::Kind::UntilIncluding, hilti::attribute::Kind::While, + hilti::attribute::Kind::IPv4, hilti::attribute::Kind::IPv6, hilti::attribute::Kind::Eod, + hilti::attribute::Kind::ByteOrder, hilti::attribute::Kind::BitOrder, hilti::attribute::Kind::Requires, + hilti::attribute::Kind::Try, hilti::attribute::Kind::Nosub, hilti::attribute::Kind::Default}}, {hilti::node::tag::type::unit::item::Block, - {hilti::Attribute::Kind::Size, hilti::Attribute::Kind::ParseAt, hilti::Attribute::Kind::ParseFrom}}, + {hilti::attribute::Kind::Size, hilti::attribute::Kind::ParseAt, hilti::attribute::Kind::ParseFrom}}, {hilti::node::tag::type::unit::item::Switch, - {hilti::Attribute::Kind::Size, hilti::Attribute::Kind::ParseAt, hilti::Attribute::Kind::ParseFrom}}, + {hilti::attribute::Kind::Size, hilti::attribute::Kind::ParseAt, hilti::attribute::Kind::ParseFrom}}, {hilti::node::tag::type::unit::item::Property, - {hilti::Attribute::Kind::Originator, hilti::Attribute::Kind::Responder}}, + {hilti::attribute::Kind::Originator, hilti::attribute::Kind::Responder}}, // The following apply only to types within a field {hilti::node::tag::type::Address, - {hilti::Attribute::Kind::IPv4, hilti::Attribute::Kind::IPv6, hilti::Attribute::Kind::ByteOrder}}, - {hilti::node::tag::type::Bitfield, {hilti::Attribute::Kind::ByteOrder, hilti::Attribute::Kind::BitOrder}}, + {hilti::attribute::Kind::IPv4, hilti::attribute::Kind::IPv6, hilti::attribute::Kind::ByteOrder}}, + {hilti::node::tag::type::Bitfield, {hilti::attribute::Kind::ByteOrder, hilti::attribute::Kind::BitOrder}}, {hilti::node::tag::type::Bytes, - {hilti::Attribute::Kind::Eod, hilti::Attribute::Kind::Until, hilti::Attribute::Kind::UntilIncluding, - hilti::Attribute::Kind::Chunked, hilti::Attribute::Kind::Nosub}}, - {hilti::node::tag::type::Real, {hilti::Attribute::Kind::Type, hilti::Attribute::Kind::ByteOrder}}, - {hilti::node::tag::type::RegExp, {hilti::Attribute::Kind::Nosub}}, - {hilti::node::tag::type::SignedInteger, {hilti::Attribute::Kind::ByteOrder, hilti::Attribute::Kind::BitOrder}}, - {hilti::node::tag::type::Unit, {hilti::Attribute::Kind::ParseAt}}, - {hilti::node::tag::type::UnsignedInteger, {hilti::Attribute::Kind::ByteOrder, hilti::Attribute::Kind::BitOrder}}, + {hilti::attribute::Kind::Eod, hilti::attribute::Kind::Until, hilti::attribute::Kind::UntilIncluding, + hilti::attribute::Kind::Chunked, hilti::attribute::Kind::Nosub}}, + {hilti::node::tag::type::Real, {hilti::attribute::Kind::Type, hilti::attribute::Kind::ByteOrder}}, + {hilti::node::tag::type::RegExp, {hilti::attribute::Kind::Nosub}}, + {hilti::node::tag::type::SignedInteger, {hilti::attribute::Kind::ByteOrder, hilti::attribute::Kind::BitOrder}}, + {hilti::node::tag::type::Unit, {hilti::attribute::Kind::ParseAt}}, + {hilti::node::tag::type::UnsignedInteger, {hilti::attribute::Kind::ByteOrder, hilti::attribute::Kind::BitOrder}}, {hilti::node::tag::type::Vector, - {hilti::Attribute::Kind::UntilIncluding, hilti::Attribute::Kind::While, hilti::Attribute::Kind::Until, - hilti::Attribute::Kind::Count, hilti::Attribute::Kind::Eod}}, + {hilti::attribute::Kind::UntilIncluding, hilti::attribute::Kind::While, hilti::attribute::Kind::Until, + hilti::attribute::Kind::Count, hilti::attribute::Kind::Eod}}, }; -std::unordered_set allowed_attributes_for_any_field = - {hilti::Attribute::Kind::Synchronize, hilti::Attribute::Kind::Convert, hilti::Attribute::Kind::Requires, - hilti::Attribute::Kind::Default, hilti::Attribute::Kind::Size, hilti::Attribute::Kind::MaxSize, - hilti::Attribute::Kind::Try, hilti::Attribute::Kind::ParseAt, hilti::Attribute::Kind::ParseFrom}; - +std::unordered_set allowed_attributes_for_any_field = + {hilti::attribute::Kind::Synchronize, hilti::attribute::Kind::Convert, hilti::attribute::Kind::Requires, + hilti::attribute::Kind::Default, hilti::attribute::Kind::Size, hilti::attribute::Kind::MaxSize, + hilti::attribute::Kind::Try, hilti::attribute::Kind::ParseAt, hilti::attribute::Kind::ParseFrom}; bool isEnumType(QualifiedType* t, const char* expected_id) { return t->type()->typeID() && t->type()->typeID() == ID(expected_id); @@ -93,34 +92,34 @@ bool supportsLiterals(QualifiedType* t) { // Helper to make sure a field's attributes are consistent. This is type-independent. hilti::Result checkFieldAttributes(type::unit::item::Field* f) { // Can't combine ipv4 and ipv6 - auto v4 = f->attributes()->has(hilti::Attribute::Kind::IPv4); - auto v6 = f->attributes()->has(hilti::Attribute::Kind::IPv6); + auto v4 = f->attributes()->has(hilti::attribute::Kind::IPv4); + auto v6 = f->attributes()->has(hilti::attribute::Kind::IPv6); if ( v4 && v6 ) return hilti::result::Error("field cannot have both &ipv4 and &ipv6 attributes"); // Termination conditions cannot be combined in certain ways - auto eod_attr = f->attributes()->find(hilti::Attribute::Kind::Eod); - auto until_attr = f->attributes()->find(hilti::Attribute::Kind::Until); - auto until_including_attr = f->attributes()->find(hilti::Attribute::Kind::UntilIncluding); - auto parse_at_attr = f->attributes()->find(hilti::Attribute::Kind::ParseAt); - auto parse_from_attr = f->attributes()->find(hilti::Attribute::Kind::ParseFrom); - auto size_attr = f->attributes()->find(hilti::Attribute::Kind::Size); - auto max_size_attr = f->attributes()->find(hilti::Attribute::Kind::MaxSize); - - std::vector start_attrs_present; + auto eod_attr = f->attributes()->find(hilti::attribute::Kind::Eod); + auto until_attr = f->attributes()->find(hilti::attribute::Kind::Until); + auto until_including_attr = f->attributes()->find(hilti::attribute::Kind::UntilIncluding); + auto parse_at_attr = f->attributes()->find(hilti::attribute::Kind::ParseAt); + auto parse_from_attr = f->attributes()->find(hilti::attribute::Kind::ParseFrom); + auto size_attr = f->attributes()->find(hilti::attribute::Kind::Size); + auto max_size_attr = f->attributes()->find(hilti::attribute::Kind::MaxSize); + + std::vector start_attrs_present; for ( const auto& i : {parse_from_attr, parse_at_attr} ) { if ( i ) start_attrs_present.emplace_back(i->kind()); } - std::vector end_attrs_present; + std::vector end_attrs_present; for ( const auto& i : {eod_attr, until_attr, until_including_attr} ) { if ( i ) end_attrs_present.emplace_back(i->kind()); } - std::vector size_attrs_present; + std::vector size_attrs_present; for ( const auto& i : {size_attr, max_size_attr} ) { if ( i ) size_attrs_present.emplace_back(i->kind()); @@ -131,7 +130,7 @@ hilti::Result checkFieldAttributes(type::unit::item::Field* f) { // Transform attribute kinds into strings for the diagnostic std::vector attr_strings(attrs_present->size()); std::transform(attrs_present->begin(), attrs_present->end(), attr_strings.begin(), - [](const hilti::Attribute::Kind kind) { return hilti::Attribute::kindToString(kind); }); + [](const hilti::attribute::Kind kind) { return to_string(kind); }); return hilti::result::Error( fmt("attributes cannot be combined: %s", hilti::util::join(attr_strings, ", "))); } @@ -152,9 +151,9 @@ hilti::Result isParseableType(QualifiedType* pt, type::unit::ite if ( f->ctor() ) return hilti::Nothing(); - const auto required_one_of = {hilti::Attribute::Kind::Eod, hilti::Attribute::Kind::ParseAt, - hilti::Attribute::Kind::ParseFrom, hilti::Attribute::Kind::Size, - hilti::Attribute::Kind::Until, hilti::Attribute::Kind::UntilIncluding}; + const auto required_one_of = {hilti::attribute::Kind::Eod, hilti::attribute::Kind::ParseAt, + hilti::attribute::Kind::ParseFrom, hilti::attribute::Kind::Size, + hilti::attribute::Kind::Until, hilti::attribute::Kind::UntilIncluding}; // Make sure we have one of the required attributes for ( const auto& attr : required_one_of ) { @@ -164,13 +163,13 @@ hilti::Result isParseableType(QualifiedType* pt, type::unit::ite std::vector attr_strings(required_one_of.size()); std::transform(required_one_of.begin(), required_one_of.end(), attr_strings.begin(), - [](const hilti::Attribute::Kind kind) { return hilti::Attribute::kindToString(kind); }); + [](const hilti::attribute::Kind kind) { return to_string(kind); }); return hilti::result::Error(fmt("bytes field requires one of %s", hilti::util::join(attr_strings, ", "))); } if ( pt->type()->isA() ) { - auto v4 = f->attributes()->has(hilti::Attribute::Kind::IPv4); - auto v6 = f->attributes()->has(hilti::Attribute::Kind::IPv6); + auto v4 = f->attributes()->has(hilti::attribute::Kind::IPv4); + auto v6 = f->attributes()->has(hilti::attribute::Kind::IPv6); if ( ! (v4 || v6) ) return hilti::result::Error("address field must come with either &ipv4 or &ipv6 attribute"); @@ -179,7 +178,7 @@ hilti::Result isParseableType(QualifiedType* pt, type::unit::ite } if ( pt->type()->isA() ) { - auto type = f->attributes()->find(hilti::Attribute::Kind::Type); + auto type = f->attributes()->find(hilti::attribute::Kind::Type); if ( type ) { if ( const auto& t = (*type->valueAsExpression())->type(); ! isEnumType(t, "spicy::RealType") ) @@ -268,7 +267,7 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { for ( const auto& attr : attributes->attributes() ) if ( allowed.find(attr->kind()) == allowed.end() ) - error(hilti::util::fmt("invalid attribute '%s' in %s", attr->attributeName(), where), attr); + error(hilti::util::fmt("invalid attribute '%s' in %s", to_string(attr->kind()), where), attr); } // Ensures that the type represented by typeTag can be within a field with @@ -279,7 +278,7 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { if ( ! attributes ) return; - std::unordered_set type_specific_attrs = {}; + std::unordered_set type_specific_attrs = {}; auto it = allowed_attributes.find(typeTag); if ( it != allowed_attributes.end() ) type_specific_attrs = it->second; @@ -287,7 +286,8 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { for ( const auto& attr : attributes->attributes() ) { if ( allowed_attributes_for_any_field.find(attr->kind()) == allowed_attributes_for_any_field.end() && type_specific_attrs.find(attr->kind()) == type_specific_attrs.end() ) - error(hilti::util::fmt("invalid attribute '%s' for field with type '%s'", attr->attributeName(), clazz), + error(hilti::util::fmt("invalid attribute '%s' for field with type '%s'", to_string(attr->kind()), + clazz), attr); } } @@ -334,8 +334,8 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { if ( auto attr = n->parent() ) { auto kind = attr->kind(); - if ( kind == hilti::Attribute::Kind::Until || kind == hilti::Attribute::Kind::UntilIncluding || - kind == hilti::Attribute::Kind::While ) + if ( kind == hilti::attribute::Kind::Until || kind == hilti::attribute::Kind::UntilIncluding || + kind == hilti::attribute::Kind::While ) // $$ inside these attributes is ok return; } @@ -593,11 +593,11 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { checkNodeAttributes(n->nodeTag(), n->attributes(), "hook declaration"); if ( auto field = n->parent(); - field && n->attributes()->has(hilti::Attribute::Kind::Foreach) && ! field->isContainer() ) + field && n->attributes()->has(hilti::attribute::Kind::Foreach) && ! field->isContainer() ) error("'foreach' can only be used with containers", n); - if ( n->attributes()->has(hilti::Attribute::Kind::Foreach) && - n->attributes()->has(hilti::Attribute::Kind::Error) ) + if ( n->attributes()->has(hilti::attribute::Kind::Foreach) && + n->attributes()->has(hilti::attribute::Kind::Error) ) error("hook cannot have both 'foreach' and '%error'", n); // Ensure we only have one foreach or one %error @@ -605,9 +605,9 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { int err_count = 0; if ( auto attrs = n->attributes() ) { for ( const auto& attr : attrs->attributes() ) { - if ( attr->kind() == hilti::Attribute::Kind::Foreach ) + if ( attr->kind() == hilti::attribute::Kind::Foreach ) foreach_count++; - else if ( attr->kind() == hilti::Attribute::Kind::Error ) + else if ( attr->kind() == hilti::attribute::Kind::Error ) err_count++; } } @@ -645,16 +645,16 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { return nullptr; }; - if ( hilti::Attribute::isOneOf(n->kind(), - {hilti::Attribute::Kind::Size, hilti::Attribute::Kind::MaxSize, - hilti::Attribute::Kind::ByteOrder, hilti::Attribute::Kind::Convert, - hilti::Attribute::Kind::Until, hilti::Attribute::Kind::While, - hilti::Attribute::Kind::UntilIncluding, hilti::Attribute::Kind::ParseFrom, - hilti::Attribute::Kind::ParseAt, hilti::Attribute::Kind::Requires}) && + if ( hilti::attribute::isOneOf(n->kind(), + {hilti::attribute::Kind::Size, hilti::attribute::Kind::MaxSize, + hilti::attribute::Kind::ByteOrder, hilti::attribute::Kind::Convert, + hilti::attribute::Kind::Until, hilti::attribute::Kind::While, + hilti::attribute::Kind::UntilIncluding, hilti::attribute::Kind::ParseFrom, + hilti::attribute::Kind::ParseAt, hilti::attribute::Kind::Requires}) && ! n->hasValue() ) - error(fmt("%s must provide an expression", n->attributeName()), n); + error(fmt("%s must provide an expression", to_string(n->kind())), n); - else if ( n->kind() == hilti::Attribute::Kind::Default ) { + else if ( n->kind() == hilti::attribute::Kind::Default ) { if ( get_attr_field(n) ) { if ( ! n->hasValue() ) error("&default requires an argument", n); @@ -668,7 +668,7 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { } } - else if ( n->kind() == hilti::Attribute::Kind::Eod ) { + else if ( n->kind() == hilti::attribute::Kind::Eod ) { if ( auto f = get_attr_field(n) ) { if ( ! (f->parseType()->type()->isA() || f->parseType()->type()->isA()) || @@ -677,46 +677,46 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { } } - else if ( hilti::Attribute::isOneOf(n->kind(), - {hilti::Attribute::Kind::While, hilti::Attribute::Kind::UntilIncluding, - hilti::Attribute::Kind::Until}) ) { + else if ( hilti::attribute::isOneOf(n->kind(), + {hilti::attribute::Kind::While, hilti::attribute::Kind::UntilIncluding, + hilti::attribute::Kind::Until}) ) { if ( auto f = get_attr_field(n) ) { if ( ! (f->parseType()->type()->isA() || f->parseType()->type()->isA()) ) - error(fmt("%s is only valid for fields of type bytes or vector", n->attributeName()), n); + error(fmt("%s is only valid for fields of type bytes or vector", to_string(n->kind())), n); } } - else if ( n->kind() == hilti::Attribute::Kind::Chunked ) { + else if ( n->kind() == hilti::attribute::Kind::Chunked ) { if ( auto f = get_attr_field(n) ) { if ( ! f->parseType()->type()->isA() || f->ctor() ) error("&chunked is only valid for bytes fields", n); else if ( n->hasValue() ) error("&chunked cannot have an expression", n); - else if ( ! (f->attributes()->has(hilti::Attribute::Kind::Eod) || - f->attributes()->has(hilti::Attribute::Kind::Size) || - f->attributes()->has(hilti::Attribute::Kind::Until) || - f->attributes()->has(hilti::Attribute::Kind::UntilIncluding)) ) + else if ( ! (f->attributes()->has(hilti::attribute::Kind::Eod) || + f->attributes()->has(hilti::attribute::Kind::Size) || + f->attributes()->has(hilti::attribute::Kind::Until) || + f->attributes()->has(hilti::attribute::Kind::UntilIncluding)) ) error("&chunked must be used with &eod, &until, &until-including or &size", n); } } - else if ( n->kind() == hilti::Attribute::Kind::Transient ) + else if ( n->kind() == hilti::attribute::Kind::Transient ) error("&transient is no longer available, use an anonymous field instead to achieve the same effect", n); - else if ( hilti::Attribute::isOneOf(n->kind(), - {hilti::Attribute::Kind::ParseFrom, hilti::Attribute::Kind::ParseAt}) ) { + else if ( hilti::attribute::isOneOf(n->kind(), + {hilti::attribute::Kind::ParseFrom, hilti::attribute::Kind::ParseAt}) ) { if ( get_attr_field(n) ) { if ( auto e = n->valueAsExpression(); e && ! hilti::type::same((*e)->type()->type(), builder.typeStreamIterator()) && ! hilti::type::same((*e)->type()->type(), builder.typeBytes()) ) error(fmt("%s must have an expression of type either bytes or iterator", - n->attributeName()), + to_string(n->kind())), n); } } - else if ( n->kind() == hilti::Attribute::Kind::Requires ) { + else if ( n->kind() == hilti::attribute::Kind::Requires ) { if ( ! n->hasValue() ) error("&requires must provide an expression", n); else { @@ -769,13 +769,13 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { checkNodeAttributes(n->nodeTag(), n->attributes(), "unit type"); if ( auto attrs = n->attributes() ) { - if ( attrs->has(hilti::Attribute::Kind::Size) && attrs->has(hilti::Attribute::Kind::MaxSize) ) + if ( attrs->has(hilti::attribute::Kind::Size) && attrs->has(hilti::attribute::Kind::MaxSize) ) error(("attributes cannot be combined: &size, &max-size"), n); for ( const auto& a : attrs->attributes() ) { - if ( a->kind() == hilti::Attribute::Kind::Size || a->kind() == hilti::Attribute::Kind::MaxSize ) { + if ( a->kind() == hilti::attribute::Kind::Size || a->kind() == hilti::attribute::Kind::MaxSize ) { if ( ! a->hasValue() ) - error(fmt("%s must provide an expression", a->attributeName()), n); + error(fmt("%s must provide an expression", to_string(a->kind())), n); else { auto v = visitor::PreOrder(); for ( auto i : visitor::range(v, a->value(), {}) ) @@ -784,14 +784,14 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { error(fmt("%s expression cannot use 'self' since it is only available after " "parsing of " "unit has started", - a->attributeName()), + to_string(a->kind())), n); break; } } } - else if ( a->kind() == hilti::Attribute::Kind::Requires ) { + else if ( a->kind() == hilti::attribute::Kind::Requires ) { auto e = a->valueAsExpression(); if ( ! e ) error(e.error(), n); @@ -803,7 +803,7 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { n); } } - else if ( a->kind() == hilti::Attribute::Kind::ByteOrder ) { + else if ( a->kind() == hilti::attribute::Kind::ByteOrder ) { auto e = a->valueAsExpression(); if ( ! e ) error(e.error(), n); @@ -814,7 +814,7 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { n); } } - else if ( a->kind() == hilti::Attribute::Kind::Convert ) { + else if ( a->kind() == hilti::attribute::Kind::Convert ) { if ( ! a->hasValue() ) error("&convert must provide an expression", n); } @@ -894,7 +894,7 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { } - const auto count_attr = n->attributes()->find(hilti::Attribute::Kind::Count); + const auto count_attr = n->attributes()->find(hilti::attribute::Kind::Count); const auto repeat = n->repeatCount(); if ( count_attr && (repeat && ! repeat->type()->type()->isA()) ) error("cannot have both '[..]' and &count", n); @@ -902,8 +902,8 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { if ( count_attr ) deprecated("&count=N is deprecated, prefer '[N]' syntax", count_attr->meta().location()); - if ( n->attributes()->has(hilti::Attribute::Kind::Convert) && - n->attributes()->has(hilti::Attribute::Kind::Chunked) ) + if ( n->attributes()->has(hilti::attribute::Kind::Convert) && + n->attributes()->has(hilti::attribute::Kind::Chunked) ) deprecated( "usage of &convert on &chunked field is ill-defined and deprecated; support will be " "removed in future versions", @@ -944,7 +944,7 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { // Check for attributes which can be used at most once. if ( n->attributes() ) { - std::unordered_map attrs; + std::unordered_map attrs; for ( const auto& a : n->attributes()->attributes() ) attrs[a->kind()] += 1; @@ -952,19 +952,19 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { if ( count <= 1 ) continue; - if ( hilti::Attribute::isOneOf(a, - {hilti::Attribute::Kind::Convert, hilti::Attribute::Kind::Size, - hilti::Attribute::Kind::MaxSize, hilti::Attribute::Kind::ParseAt, - hilti::Attribute::Kind::ParseFrom, hilti::Attribute::Kind::Type, - hilti::Attribute::Kind::Until, hilti::Attribute::Kind::UntilIncluding, - hilti::Attribute::Kind::While}) ) - error(fmt("'%s' can be used at most once", hilti::Attribute::kindToString(a)), n); + if ( hilti::attribute::isOneOf(a, + {hilti::attribute::Kind::Convert, hilti::attribute::Kind::Size, + hilti::attribute::Kind::MaxSize, hilti::attribute::Kind::ParseAt, + hilti::attribute::Kind::ParseFrom, hilti::attribute::Kind::Type, + hilti::attribute::Kind::Until, hilti::attribute::Kind::UntilIncluding, + hilti::attribute::Kind::While}) ) + error(fmt("'%s' can be used at most once", to_string(a)), n); } } if ( auto t = n->itemType()->type()->tryAs() ) { for ( const auto& b : t->bits() ) { - if ( b->attributes()->has(hilti::Attribute::Kind::BitOrder) ) + if ( b->attributes()->has(hilti::attribute::Kind::BitOrder) ) deprecated(fmt("&bit-order on bitfield item '%s' has no effect and is deprecated", b->id()), b->meta().location()); } @@ -1048,7 +1048,7 @@ struct VisitorPost : visitor::PreOrder, hilti::validator::VisitorMixIn { } } - if ( f->attributes()->has(hilti::Attribute::Kind::Synchronize) ) + if ( f->attributes()->has(hilti::attribute::Kind::Synchronize) ) error(fmt("unit switch branches cannot be &synchronize"), n); seen_fields.emplace_back(f); diff --git a/tests/Baseline/hilti.types.function.param-attrs-bogus/output b/tests/Baseline/hilti.types.function.param-attrs-bogus/output index ac88ec469..943241567 100644 --- a/tests/Baseline/hilti.types.function.param-attrs-bogus/output +++ b/tests/Baseline/hilti.types.function.param-attrs-bogus/output @@ -1,4 +1,4 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. -[error] <...>/param-attrs-bogus.hlt:8:27-8:37: invalid attribute '&bogus_attr' -[error] <...>/param-attrs-bogus.hlt:9:27-9:40: invalid attribute '&my-bad-attr' +[error] <...>/param-attrs-bogus.hlt:8:27-8:37: unknown attribute '&bogus_attr' +[error] <...>/param-attrs-bogus.hlt:9:27-9:40: unknown attribute '&my-bad-attr' [error] hiltic: parse error diff --git a/tests/Baseline/spicy.types.vector.legacy-syntax-fail/output b/tests/Baseline/spicy.types.vector.legacy-syntax-fail/output index c2a7781c3..016f7a260 100644 --- a/tests/Baseline/spicy.types.vector.legacy-syntax-fail/output +++ b/tests/Baseline/spicy.types.vector.legacy-syntax-fail/output @@ -1,10 +1,10 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. [error] <...>/legacy-syntax-fail.spicy:7:8-7:20: vector syntax is no longer supported for parsing sequences; use T[] instead. -[error] <...>/legacy-syntax-fail.spicy:7:22-7:30: invalid attribute '&length' +[error] <...>/legacy-syntax-fail.spicy:7:22-7:30: unknown attribute '&length' [error] <...>/legacy-syntax-fail.spicy:8:9-8:21: vector syntax is no longer supported for parsing sequences; use T[] instead. -[error] <...>/legacy-syntax-fail.spicy:8:26-8:34: invalid attribute '&length' +[error] <...>/legacy-syntax-fail.spicy:8:26-8:34: unknown attribute '&length' [error] <...>/legacy-syntax-fail.spicy:9:10-9:22: vector syntax is no longer supported for parsing sequences; use T[] instead. -[error] <...>/legacy-syntax-fail.spicy:9:25-9:33: invalid attribute '&length' +[error] <...>/legacy-syntax-fail.spicy:9:25-9:33: unknown attribute '&length' [error] <...>/legacy-syntax-fail.spicy:10:10-10:22: vector syntax is no longer supported for parsing sequences; use T[] instead. -[error] <...>/legacy-syntax-fail.spicy:10:28-10:36: invalid attribute '&length' +[error] <...>/legacy-syntax-fail.spicy:10:28-10:36: unknown attribute '&length' [error] spicyc: parse error