diff --git a/DEPENDENCIES b/DEPENDENCIES index d907ae9ab..7d9ec3642 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,3 +1,3 @@ vendorpull https://github.com/sourcemeta/vendorpull 1dcbac42809cf87cb5b045106b863e17ad84ba02 -core https://github.com/sourcemeta/core 10f0f36b678790354d3f67c73c686dfbd0e40231 +core https://github.com/sourcemeta/core 0e963f3e966143def590ebdb643ec6c07b7ebef7 jsonschema-test-suite https://github.com/json-schema-org/JSON-Schema-Test-Suite Test-JSON-Schema-Acceptance-1.033 diff --git a/src/compiler/default_compiler_draft4.h b/src/compiler/default_compiler_draft4.h index fd8eae4ea..111629f34 100644 --- a/src/compiler/default_compiler_draft4.h +++ b/src/compiler/default_compiler_draft4.h @@ -376,15 +376,14 @@ auto compiler_draft4_validation_type(const Context &context, return {}; } + ValueTypes types{}; + types.set(static_cast(sourcemeta::core::JSON::Type::Real)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Integer)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Decimal)); return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrictAny, - context, schema_context, dynamic_context, - static_cast( - (1U << static_cast( - sourcemeta::core::JSON::Type::Real)) | - (1U << static_cast( - sourcemeta::core::JSON::Type::Integer)) | - (1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))))}; + context, schema_context, dynamic_context, types)}; } else if (type == "integer") { if (context.mode == Mode::FastValidation && schema_context.schema.defines("enum") && @@ -457,15 +456,14 @@ auto compiler_draft4_validation_type(const Context &context, context, schema_context, dynamic_context, sourcemeta::core::JSON::Type::Array)}; } else if (type == "number") { + ValueTypes types{}; + types.set(static_cast(sourcemeta::core::JSON::Type::Real)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Integer)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Decimal)); return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrictAny, - context, schema_context, dynamic_context, - static_cast( - (1U << static_cast( - sourcemeta::core::JSON::Type::Real)) | - (1U << static_cast( - sourcemeta::core::JSON::Type::Integer)) | - (1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))))}; + context, schema_context, dynamic_context, types)}; } else if (type == "integer") { return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrict, context, schema_context, dynamic_context, @@ -478,40 +476,40 @@ auto compiler_draft4_validation_type(const Context &context, return {}; } } else if (schema_context.schema.at(dynamic_context.keyword).is_array()) { - ValueTypes types{0}; + ValueTypes types{}; for (const auto &type : schema_context.schema.at(dynamic_context.keyword).as_array()) { assert(type.is_string()); const auto &type_string{type.to_string()}; if (type_string == "null") { - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Null)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Null)); } else if (type_string == "boolean") { - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Boolean)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Boolean)); } else if (type_string == "object") { - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Object)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Object)); } else if (type_string == "array") { - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Array)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Array)); } else if (type_string == "number") { - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Integer)); - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Real)); - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Decimal)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Integer)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Real)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Decimal)); } else if (type_string == "integer") { - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Integer)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Integer)); } else if (type_string == "string") { - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::String)); + types.set( + static_cast(sourcemeta::core::JSON::Type::String)); } } - assert(types != 0); + assert(types.any()); return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrictAny, context, schema_context, dynamic_context, types)}; } @@ -720,13 +718,13 @@ auto compiler_draft4_applicator_anyof(const Context &context, sourcemeta::blaze::InstructionIndex:: AssertionTypeStrictAny); })) { - ValueTypes types{0}; + ValueTypes types{}; for (const auto &instruction : disjunctors) { if (instruction.children.front().type == sourcemeta::blaze::InstructionIndex::AssertionTypeStrict) { const auto &value{ *std::get_if(&instruction.children.front().value)}; - types |= (1U << static_cast(value)); + types.set(static_cast(value)); } if (instruction.children.front().type == @@ -737,18 +735,18 @@ auto compiler_draft4_applicator_anyof(const Context &context, } } - assert(types != 0); - std::uint8_t popcount{0}; - for (std::uint8_t temp{types}; temp != 0; temp >>= 1) { - popcount += (temp & 1); - } + assert(types.any()); + const auto popcount{types.count()}; if (popcount > 1) { return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrictAny, context, schema_context, dynamic_context, types)}; } else { std::uint8_t type_index{0}; - for (std::uint8_t temp{types}; (temp & 1) == 0; temp >>= 1) { - type_index++; + for (std::uint8_t bit{0}; bit < 8; bit++) { + if (types.test(bit)) { + type_index = bit; + break; + } } return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrict, context, schema_context, dynamic_context, diff --git a/src/compiler/default_compiler_draft6.h b/src/compiler/default_compiler_draft6.h index c3d213b0e..f8a716613 100644 --- a/src/compiler/default_compiler_draft6.h +++ b/src/compiler/default_compiler_draft6.h @@ -165,15 +165,14 @@ auto compiler_draft6_validation_type(const Context &context, return {}; } + ValueTypes types{}; + types.set(static_cast(sourcemeta::core::JSON::Type::Real)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Integer)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Decimal)); return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrictAny, - context, schema_context, dynamic_context, - static_cast( - (1U << static_cast( - sourcemeta::core::JSON::Type::Real)) | - (1U << static_cast( - sourcemeta::core::JSON::Type::Integer)) | - (1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))))}; + context, schema_context, dynamic_context, types)}; } else if (type == "integer") { if (context.mode == Mode::FastValidation && schema_context.schema.defines("enum") && @@ -262,15 +261,14 @@ auto compiler_draft6_validation_type(const Context &context, context, schema_context, dynamic_context, sourcemeta::core::JSON::Type::Array)}; } else if (type == "number") { + ValueTypes types{}; + types.set(static_cast(sourcemeta::core::JSON::Type::Real)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Integer)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Decimal)); return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeStrictAny, - context, schema_context, dynamic_context, - static_cast( - (1U << static_cast( - sourcemeta::core::JSON::Type::Real)) | - (1U << static_cast( - sourcemeta::core::JSON::Type::Integer)) | - (1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))))}; + context, schema_context, dynamic_context, types)}; } else if (type == "integer") { return {make(sourcemeta::blaze::InstructionIndex::AssertionType, context, schema_context, dynamic_context, @@ -287,44 +285,44 @@ auto compiler_draft6_validation_type(const Context &context, return {}; } } else if (schema_context.schema.at(dynamic_context.keyword).is_array()) { - ValueTypes types{0}; + ValueTypes types{}; for (const auto &type : schema_context.schema.at(dynamic_context.keyword).as_array()) { assert(type.is_string()); const auto &type_string{type.to_string()}; if (type_string == "null") { - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Null)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Null)); } else if (type_string == "boolean") { - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Boolean)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Boolean)); } else if (type_string == "object") { - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Object)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Object)); } else if (type_string == "array") { - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Array)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Array)); } else if (type_string == "number") { - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Integer)); - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Real)); - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Decimal)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Integer)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Real)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Decimal)); } else if (type_string == "integer") { - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::Integer)); + types.set( + static_cast(sourcemeta::core::JSON::Type::Integer)); } else if (type_string == "string") { if (dynamic_context.property_as_target) { continue; } - types |= (1U << static_cast( - sourcemeta::core::JSON::Type::String)); + types.set( + static_cast(sourcemeta::core::JSON::Type::String)); } } - assert(types != 0); + assert(types.any()); return {make(sourcemeta::blaze::InstructionIndex::AssertionTypeAny, context, schema_context, dynamic_context, types)}; } diff --git a/src/evaluator/dispatch.inc.h b/src/evaluator/dispatch.inc.h index 6f51785de..993ab2fba 100644 --- a/src/evaluator/dispatch.inc.h +++ b/src/evaluator/dispatch.inc.h @@ -268,16 +268,14 @@ INSTRUCTION_HANDLER(AssertionTypeAny) { SOURCEMETA_MAYBE_UNUSED(evaluator); EVALUATE_BEGIN_NO_PRECONDITION(AssertionTypeAny); const auto value{*std::get_if(&instruction.value)}; - assert(value != 0); + assert(value.any()); const auto &target{get(instance, instruction.relative_instance_location)}; // In non-strict mode, we consider a real number that represents an // integer to be an integer - const auto type_bit{static_cast( - 1U << static_cast(target.type()))}; - if ((value & type_bit) != 0) { + const auto type_index{static_cast(target.type())}; + if (value.test(type_index)) { result = true; - } else if ((value & (1U << static_cast(JSON::Type::Integer))) != - 0 && + } else if (value.test(static_cast(JSON::Type::Integer)) && target.is_integral()) { result = true; } @@ -308,11 +306,11 @@ INSTRUCTION_HANDLER(AssertionTypeStrictAny) { SOURCEMETA_MAYBE_UNUSED(evaluator); EVALUATE_BEGIN_NO_PRECONDITION(AssertionTypeStrictAny); const auto value{*std::get_if(&instruction.value)}; - assert(value != 0); + assert(value.any()); const auto &target{get(instance, instruction.relative_instance_location)}; - const auto type_bit{static_cast( - 1U << static_cast(effective_type_strict_real(target)))}; - result = ((value & type_bit) != 0); + const auto type_index{ + static_cast(effective_type_strict_real(target))}; + result = value.test(type_index); EVALUATE_END(AssertionTypeStrictAny); } @@ -782,14 +780,12 @@ INSTRUCTION_HANDLER(AssertionPropertyTypeStrictAny) { SOURCEMETA_MAYBE_UNUSED(evaluator); EVALUATE_BEGIN_TRY_TARGET(AssertionPropertyTypeStrictAny); const auto value{*std::get_if(&instruction.value)}; - assert(value != 0); + assert(value.any()); // Now here we refer to the actual property - const auto type_bit{static_cast( - 1U << static_cast(target_check->type()))}; + const auto type_index{static_cast(target_check->type())}; result = - ((value & type_bit) != 0) || - (((value & (1U << static_cast(JSON::Type::Integer))) != - 0) && + value.test(type_index) || + (value.test(static_cast(JSON::Type::Integer)) && target_check->is_decimal() && target_check->to_decimal().is_integer()); EVALUATE_END(AssertionPropertyTypeStrictAny); } @@ -803,11 +799,10 @@ INSTRUCTION_HANDLER(AssertionPropertyTypeStrictAnyEvaluate) { SOURCEMETA_MAYBE_UNUSED(evaluator); EVALUATE_BEGIN_TRY_TARGET(AssertionPropertyTypeStrictAnyEvaluate); const auto value{*std::get_if(&instruction.value)}; - assert(value != 0); + assert(value.any()); // Now here we refer to the actual property - const auto type_bit{static_cast( - 1U << static_cast(target_check->type()))}; - result = ((value & type_bit) != 0); + const auto type_index{static_cast(target_check->type())}; + result = value.test(type_index); if (result) { evaluator.evaluate(target_check); @@ -2069,12 +2064,11 @@ INSTRUCTION_HANDLER(LoopPropertiesTypeStrictAny) { EVALUATE_BEGIN_NON_STRING(LoopPropertiesTypeStrictAny, target.is_object()); result = true; const auto value{*std::get_if(&instruction.value)}; - assert(value != 0); + assert(value.any()); for (const auto &entry : target.as_object()) { - const auto type_bit{static_cast( - 1U << static_cast( - effective_type_strict_real(entry.second)))}; - if ((value & type_bit) == 0) { + const auto type_index{ + static_cast(effective_type_strict_real(entry.second))}; + if (!value.test(type_index)) { result = false; break; } @@ -2094,12 +2088,11 @@ INSTRUCTION_HANDLER(LoopPropertiesTypeStrictAnyEvaluate) { target.is_object()); result = true; const auto value{*std::get_if(&instruction.value)}; - assert(value != 0); + assert(value.any()); for (const auto &entry : target.as_object()) { - const auto type_bit{static_cast( - 1U << static_cast( - effective_type_strict_real(entry.second)))}; - if ((value & type_bit) == 0) { + const auto type_index{ + static_cast(effective_type_strict_real(entry.second))}; + if (!value.test(type_index)) { result = false; EVALUATE_END(LoopPropertiesTypeStrictAnyEvaluate); } @@ -2344,13 +2337,13 @@ INSTRUCTION_HANDLER(LoopItemsTypeStrictAny) { SOURCEMETA_MAYBE_UNUSED(evaluator); EVALUATE_BEGIN_NON_STRING(LoopItemsTypeStrictAny, target.is_array()); const auto value{*std::get_if(&instruction.value)}; - assert(value != 0); + assert(value.any()); result = true; for (const auto &entry : target.as_array()) { - const auto type_bit{static_cast( - 1U << static_cast(effective_type_strict_real(entry)))}; - if ((value & type_bit) == 0) { + const auto type_index{ + static_cast(effective_type_strict_real(entry))}; + if (!value.test(type_index)) { result = false; break; } diff --git a/src/evaluator/evaluator_describe.cc b/src/evaluator/evaluator_describe.cc index a596bf4a0..4e2dc91e9 100644 --- a/src/evaluator/evaluator_describe.cc +++ b/src/evaluator/evaluator_describe.cc @@ -73,40 +73,35 @@ auto describe_types_check(const bool valid, const ValueTypes expected, std::ostringstream &message) -> void { ValueTypes types{expected}; - const auto has_real{(types & (1U << static_cast( - sourcemeta::core::JSON::Type::Real))) != 0}; - const auto has_integer{ - (types & (1U << static_cast( - sourcemeta::core::JSON::Type::Integer))) != 0}; - const auto has_decimal{ - (types & (1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))) != 0}; + const auto has_real{types.test( + static_cast(sourcemeta::core::JSON::Type::Real))}; + const auto has_integer{types.test( + static_cast(sourcemeta::core::JSON::Type::Integer))}; + const auto has_decimal{types.test( + static_cast(sourcemeta::core::JSON::Type::Decimal))}; if (has_real && has_integer) { - types &= static_cast( - ~(1U << static_cast( - sourcemeta::core::JSON::Type::Integer))); + types.reset( + static_cast(sourcemeta::core::JSON::Type::Integer)); } if (has_real && has_decimal) { - types &= static_cast( - ~(1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))); + types.reset( + static_cast(sourcemeta::core::JSON::Type::Decimal)); } if (has_integer && has_decimal) { - types &= static_cast( - ~(1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))); + types.reset( + static_cast(sourcemeta::core::JSON::Type::Decimal)); } - std::uint8_t popcount{0}; - for (std::uint8_t temp{types}; temp != 0; temp >>= 1) { - popcount += (temp & 1); - } + const auto popcount{types.count()}; if (popcount == 1) { std::uint8_t type_index{0}; - for (std::uint8_t temp{types}; (temp & 1) == 0; temp >>= 1) { - type_index++; + for (std::uint8_t bit{0}; bit < 8; bit++) { + if (types.test(bit)) { + type_index = bit; + break; + } } describe_type_check(valid, current, static_cast(type_index), @@ -118,13 +113,13 @@ auto describe_types_check(const bool valid, bool first{true}; std::uint8_t last_bit{255}; for (std::uint8_t bit{0}; bit < 8; bit++) { - if ((types & (1U << bit)) != 0) { + if (types.test(bit)) { last_bit = bit; } } for (std::uint8_t bit{0}; bit < 8; bit++) { - if ((types & (1U << bit)) != 0) { + if (types.test(bit)) { if (!first) { message << ", "; } @@ -806,41 +801,35 @@ auto describe(const bool valid, const Instruction &step, message << "The object properties were expected to be of type "; ValueTypes types{instruction_value(step)}; - const auto has_real{(types & (1U << static_cast( - sourcemeta::core::JSON::Type::Real))) != - 0}; - const auto has_integer{ - (types & (1U << static_cast( - sourcemeta::core::JSON::Type::Integer))) != 0}; - const auto has_decimal{ - (types & (1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))) != 0}; + const auto has_real{types.test( + static_cast(sourcemeta::core::JSON::Type::Real))}; + const auto has_integer{types.test( + static_cast(sourcemeta::core::JSON::Type::Integer))}; + const auto has_decimal{types.test( + static_cast(sourcemeta::core::JSON::Type::Decimal))}; if (has_real && has_integer) { - types &= static_cast( - ~(1U << static_cast( - sourcemeta::core::JSON::Type::Integer))); + types.reset( + static_cast(sourcemeta::core::JSON::Type::Integer)); } if (has_real && has_decimal) { - types &= static_cast( - ~(1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))); + types.reset( + static_cast(sourcemeta::core::JSON::Type::Decimal)); } if (has_integer && has_decimal) { - types &= static_cast( - ~(1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))); + types.reset( + static_cast(sourcemeta::core::JSON::Type::Decimal)); } - std::uint8_t popcount{0}; - for (std::uint8_t temp{types}; temp != 0; temp >>= 1) { - popcount += (temp & 1); - } + const auto popcount{types.count()}; if (popcount == 1) { std::uint8_t type_index{0}; - for (std::uint8_t temp{types}; (temp & 1) == 0; temp >>= 1) { - type_index++; + for (std::uint8_t bit{0}; bit < 8; bit++) { + if (types.test(bit)) { + type_index = bit; + break; + } } message << to_string( static_cast(type_index)); @@ -848,13 +837,13 @@ auto describe(const bool valid, const Instruction &step, bool first{true}; std::uint8_t last_bit{255}; for (std::uint8_t bit{0}; bit < 8; bit++) { - if ((types & (1U << bit)) != 0) { + if (types.test(bit)) { last_bit = bit; } } for (std::uint8_t bit{0}; bit < 8; bit++) { - if ((types & (1U << bit)) != 0) { + if (types.test(bit)) { if (!first) { message << ", "; } @@ -876,41 +865,35 @@ auto describe(const bool valid, const Instruction &step, message << "The object properties were expected to be of type "; ValueTypes types{instruction_value(step)}; - const auto has_real{(types & (1U << static_cast( - sourcemeta::core::JSON::Type::Real))) != - 0}; - const auto has_integer{ - (types & (1U << static_cast( - sourcemeta::core::JSON::Type::Integer))) != 0}; - const auto has_decimal{ - (types & (1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))) != 0}; + const auto has_real{types.test( + static_cast(sourcemeta::core::JSON::Type::Real))}; + const auto has_integer{types.test( + static_cast(sourcemeta::core::JSON::Type::Integer))}; + const auto has_decimal{types.test( + static_cast(sourcemeta::core::JSON::Type::Decimal))}; if (has_real && has_integer) { - types &= static_cast( - ~(1U << static_cast( - sourcemeta::core::JSON::Type::Integer))); + types.reset( + static_cast(sourcemeta::core::JSON::Type::Integer)); } if (has_real && has_decimal) { - types &= static_cast( - ~(1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))); + types.reset( + static_cast(sourcemeta::core::JSON::Type::Decimal)); } if (has_integer && has_decimal) { - types &= static_cast( - ~(1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))); + types.reset( + static_cast(sourcemeta::core::JSON::Type::Decimal)); } - std::uint8_t popcount{0}; - for (std::uint8_t temp{types}; temp != 0; temp >>= 1) { - popcount += (temp & 1); - } + const auto popcount{types.count()}; if (popcount == 1) { std::uint8_t type_index{0}; - for (std::uint8_t temp{types}; (temp & 1) == 0; temp >>= 1) { - type_index++; + for (std::uint8_t bit{0}; bit < 8; bit++) { + if (types.test(bit)) { + type_index = bit; + break; + } } message << to_string( static_cast(type_index)); @@ -918,13 +901,13 @@ auto describe(const bool valid, const Instruction &step, bool first{true}; std::uint8_t last_bit{255}; for (std::uint8_t bit{0}; bit < 8; bit++) { - if ((types & (1U << bit)) != 0) { + if (types.test(bit)) { last_bit = bit; } } for (std::uint8_t bit{0}; bit < 8; bit++) { - if ((types & (1U << bit)) != 0) { + if (types.test(bit)) { if (!first) { message << ", "; } @@ -1019,41 +1002,35 @@ auto describe(const bool valid, const Instruction &step, message << "The array items were expected to be of type "; ValueTypes types{instruction_value(step)}; - const auto has_real{(types & (1U << static_cast( - sourcemeta::core::JSON::Type::Real))) != - 0}; - const auto has_integer{ - (types & (1U << static_cast( - sourcemeta::core::JSON::Type::Integer))) != 0}; - const auto has_decimal{ - (types & (1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))) != 0}; + const auto has_real{types.test( + static_cast(sourcemeta::core::JSON::Type::Real))}; + const auto has_integer{types.test( + static_cast(sourcemeta::core::JSON::Type::Integer))}; + const auto has_decimal{types.test( + static_cast(sourcemeta::core::JSON::Type::Decimal))}; if (has_real && has_integer) { - types &= static_cast( - ~(1U << static_cast( - sourcemeta::core::JSON::Type::Integer))); + types.reset( + static_cast(sourcemeta::core::JSON::Type::Integer)); } if (has_real && has_decimal) { - types &= static_cast( - ~(1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))); + types.reset( + static_cast(sourcemeta::core::JSON::Type::Decimal)); } if (has_integer && has_decimal) { - types &= static_cast( - ~(1U << static_cast( - sourcemeta::core::JSON::Type::Decimal))); + types.reset( + static_cast(sourcemeta::core::JSON::Type::Decimal)); } - std::uint8_t popcount{0}; - for (std::uint8_t temp{types}; temp != 0; temp >>= 1) { - popcount += (temp & 1); - } + const auto popcount{types.count()}; if (popcount == 1) { std::uint8_t type_index{0}; - for (std::uint8_t temp{types}; (temp & 1) == 0; temp >>= 1) { - type_index++; + for (std::uint8_t bit{0}; bit < 8; bit++) { + if (types.test(bit)) { + type_index = bit; + break; + } } message << to_string( static_cast(type_index)); @@ -1061,13 +1038,13 @@ auto describe(const bool valid, const Instruction &step, bool first{true}; std::uint8_t last_bit{255}; for (std::uint8_t bit{0}; bit < 8; bit++) { - if ((types & (1U << bit)) != 0) { + if (types.test(bit)) { last_bit = bit; } } for (std::uint8_t bit{0}; bit < 8; bit++) { - if ((types & (1U << bit)) != 0) { + if (types.test(bit)) { if (!first) { message << ", "; } diff --git a/src/evaluator/include/sourcemeta/blaze/evaluator_value.h b/src/evaluator/include/sourcemeta/blaze/evaluator_value.h index bea662158..2a92392fe 100644 --- a/src/evaluator/include/sourcemeta/blaze/evaluator_value.h +++ b/src/evaluator/include/sourcemeta/blaze/evaluator_value.h @@ -7,6 +7,7 @@ #include +#include // std::bitset #include // std::uint8_t #include // std::optional #include // std::string @@ -59,8 +60,7 @@ using ValueStringSet = StringSet; /// @ingroup evaluator /// Represents a compiler step JSON types value as a bitmask -/// Each bit represents a type: bit 0 = Null, bit 1 = Boolean, etc. -using ValueTypes = std::uint8_t; +using ValueTypes = std::bitset<8>; /// @ingroup evaluator /// Represents a compiler step JSON type value diff --git a/vendor/core/cmake/FindPCRE2.cmake b/vendor/core/cmake/FindPCRE2.cmake index 98b5c4561..a3cf0ae4d 100644 --- a/vendor/core/cmake/FindPCRE2.cmake +++ b/vendor/core/cmake/FindPCRE2.cmake @@ -96,6 +96,19 @@ if(NOT PCRE2_FOUND) set(SLJIT_SOURCES "${SLJIT_DIR}/sljitLir.c") add_library(sljit STATIC ${SLJIT_SOURCES}) + sourcemeta_add_default_options(PRIVATE sljit) + + if(SOURCEMETA_COMPILER_LLVM OR SOURCEMETA_COMPILER_GCC) + target_compile_options(sljit PRIVATE -Wno-double-promotion) + target_compile_options(sljit PRIVATE -Wno-conditional-uninitialized) + endif() + + if(SOURCEMETA_COMPILER_MSVC) + target_compile_options(sljit PRIVATE /sdl-) + target_compile_options(sljit PRIVATE /wd4701) + target_compile_options(sljit PRIVATE /wd4702) + target_compile_options(sljit PRIVATE /wd4127) + endif() target_include_directories(sljit PUBLIC "$" @@ -115,6 +128,26 @@ if(NOT PCRE2_FOUND) EXPORT_NAME sljit) add_library(pcre2 ${PCRE2_SOURCES}) + sourcemeta_add_default_options(PRIVATE pcre2) + + if(SOURCEMETA_COMPILER_LLVM OR SOURCEMETA_COMPILER_GCC) + target_compile_options(pcre2 PRIVATE -Wno-implicit-int-conversion) + target_compile_options(pcre2 PRIVATE -Wno-sign-conversion) + target_compile_options(pcre2 PRIVATE -Wno-comma) + target_compile_options(pcre2 PRIVATE -Wno-conditional-uninitialized) + target_compile_options(pcre2 PRIVATE -Wno-overlength-strings) + target_compile_options(pcre2 PRIVATE -Wno-conversion) + target_compile_options(pcre2 PRIVATE -Wno-type-limits) + endif() + + if(SOURCEMETA_COMPILER_MSVC) + target_compile_options(pcre2 PRIVATE /sdl-) + target_compile_options(pcre2 PRIVATE /wd4127) + target_compile_options(pcre2 PRIVATE /wd4244) + target_compile_options(pcre2 PRIVATE /wd4389) + target_compile_options(pcre2 PRIVATE /wd4701) + target_compile_options(pcre2 PRIVATE /wd4702) + endif() target_include_directories(pcre2 PRIVATE "${PCRE2_BINARY_DIR}/interface" diff --git a/vendor/core/cmake/Findmpdecimal.cmake b/vendor/core/cmake/Findmpdecimal.cmake index 34f02d05b..01c31c74f 100644 --- a/vendor/core/cmake/Findmpdecimal.cmake +++ b/vendor/core/cmake/Findmpdecimal.cmake @@ -52,6 +52,19 @@ if(NOT mpdecimal_FOUND) endif() add_library(mpdecimal ${MPDECIMAL_SOURCES}) + sourcemeta_add_default_options(PRIVATE mpdecimal) + + if(SOURCEMETA_COMPILER_LLVM OR SOURCEMETA_COMPILER_GCC) + target_compile_options(mpdecimal PRIVATE -Wno-sign-conversion) + target_compile_options(mpdecimal PRIVATE -Wno-implicit-fallthrough) + target_compile_options(mpdecimal PRIVATE -Wno-conversion) + endif() + + if(SOURCEMETA_COMPILER_MSVC) + target_compile_options(mpdecimal PRIVATE /wd4200) + target_compile_options(mpdecimal PRIVATE /wd4702) + target_compile_options(mpdecimal PRIVATE /wd4996) + endif() target_include_directories(mpdecimal PRIVATE "${MPDECIMAL_SOURCE_DIR}") diff --git a/vendor/core/cmake/Findyaml.cmake b/vendor/core/cmake/Findyaml.cmake index 035aa7013..2e4c160c8 100644 --- a/vendor/core/cmake/Findyaml.cmake +++ b/vendor/core/cmake/Findyaml.cmake @@ -15,10 +15,31 @@ if(NOT Yaml_FOUND) "${YAML_DIR}/src/yaml_private.h") add_library(yaml ${YAML_SOURCES}) + sourcemeta_add_default_options(PRIVATE yaml) if(SOURCEMETA_COMPILER_LLVM OR SOURCEMETA_COMPILER_GCC) target_compile_options(yaml PRIVATE -Wno-implicit-function-declaration) target_compile_options(yaml PRIVATE -Wno-int-to-pointer-cast) + target_compile_options(yaml PRIVATE -Wno-shadow) + target_compile_options(yaml PRIVATE -Wno-sign-conversion) + target_compile_options(yaml PRIVATE -Wno-shorten-64-to-32) + target_compile_options(yaml PRIVATE -Wno-newline-eof) + target_compile_options(yaml PRIVATE -Wno-conditional-uninitialized) + target_compile_options(yaml PRIVATE -Wno-implicit-int-conversion) + target_compile_options(yaml PRIVATE -Wno-conversion) + target_compile_options(yaml PRIVATE -Wno-unused-value) + endif() + + if(SOURCEMETA_COMPILER_MSVC) + target_compile_options(yaml PRIVATE /wd4996) + target_compile_options(yaml PRIVATE /wd4456) + target_compile_options(yaml PRIVATE /wd4457) + target_compile_options(yaml PRIVATE /wd4267) + target_compile_options(yaml PRIVATE /wd4244) + target_compile_options(yaml PRIVATE /wd4100) + target_compile_options(yaml PRIVATE /wd4245) + target_compile_options(yaml PRIVATE /wd4701) + target_compile_options(yaml PRIVATE /wd4702) endif() if(SOURCEMETA_OS_LINUX) diff --git a/vendor/core/cmake/common/compiler/options.cmake b/vendor/core/cmake/common/compiler/options.cmake index 228022a13..1c14a1678 100644 --- a/vendor/core/cmake/common/compiler/options.cmake +++ b/vendor/core/cmake/common/compiler/options.cmake @@ -2,12 +2,12 @@ function(sourcemeta_add_default_options visibility target) if(SOURCEMETA_COMPILER_MSVC) # See https://learn.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-by-category target_compile_options("${target}" ${visibility} - /options:strict - /permissive- - /W4 - /WL - /MP - /sdl) + $<$,$>:/options:strict> + $<$,$>:/permissive-> + $<$,$>:/W4> + $<$,$>:/WL> + $<$,$>:/MP> + $<$,$>:/sdl>) elseif(SOURCEMETA_COMPILER_LLVM OR SOURCEMETA_COMPILER_GCC) target_compile_options("${target}" ${visibility} -Wall @@ -37,9 +37,9 @@ function(sourcemeta_add_default_options visibility target) -Wsign-compare -Wsign-conversion -Wunknown-pragmas - -Wnon-virtual-dtor - -Woverloaded-virtual - -Winvalid-offsetof + $<$,$>:-Wnon-virtual-dtor> + $<$,$>:-Woverloaded-virtual> + $<$,$>:-Winvalid-offsetof> -funroll-loops -fstrict-aliasing -ftree-vectorize @@ -84,11 +84,11 @@ function(sourcemeta_add_default_options visibility target) target_compile_options("${target}" ${visibility} -fno-trapping-math # Newer versions of GCC (i.e. 14) seem to print a lot of false-positives here - -Wno-dangling-reference + $<$,$>:-Wno-dangling-reference> # GCC seems to print a lot of false-positives here -Wno-free-nonheap-object # Disables runtime type information - -fno-rtti) + $<$,$>:-fno-rtti>) endif() endfunction() diff --git a/vendor/core/src/core/json/include/sourcemeta/core/json_auto.h b/vendor/core/src/core/json/include/sourcemeta/core/json_auto.h index 39896a4ca..c84630727 100644 --- a/vendor/core/src/core/json/include/sourcemeta/core/json_auto.h +++ b/vendor/core/src/core/json/include/sourcemeta/core/json_auto.h @@ -4,6 +4,7 @@ #include #include // std::sort +#include // std::bitset #include // assert #include // std::chrono #include // std::same_as, std::constructible_from @@ -29,6 +30,17 @@ template struct json_auto_is_basic_string> : std::true_type {}; +/// @ingroup json +template struct json_auto_is_bitset : std::false_type {}; +template +struct json_auto_is_bitset> : std::true_type {}; + +/// @ingroup json +template struct json_auto_bitset_size; +template +struct json_auto_bitset_size> + : std::integral_constant {}; + /// @ingroup json template concept json_auto_has_method_from = requires(const JSON &value) { @@ -272,6 +284,38 @@ auto from_json(const JSON &value) -> std::optional { } } +/// @ingroup json +template + requires json_auto_is_bitset::value +auto to_json(const T &bitset) -> JSON { + constexpr std::size_t N{json_auto_bitset_size::value}; + if constexpr (N <= 64) { + return JSON{static_cast(bitset.to_ullong())}; + } else { + return JSON{bitset.to_string()}; + } +} + +/// @ingroup json +template + requires json_auto_is_bitset::value +auto from_json(const JSON &value) -> std::optional { + constexpr std::size_t N{json_auto_bitset_size::value}; + if constexpr (N <= 64) { + if (value.is_integer()) { + return T{static_cast(value.to_integer())}; + } else { + return std::nullopt; + } + } else { + if (value.is_string()) { + return T{value.to_string()}; + } else { + return std::nullopt; + } + } +} + /// @ingroup json template requires std::is_same_v