@@ -389,6 +389,30 @@ auto properties_as_loop(const Context &context,
389389 }));
390390}
391391
392+ auto draft3_set_type_bits (const std::string &name, ValueTypes &types) -> bool {
393+ using sourcemeta::core::JSON;
394+ if (name == " null" ) {
395+ types.set (std::to_underlying (JSON::Type::Null));
396+ } else if (name == " boolean" ) {
397+ types.set (std::to_underlying (JSON::Type::Boolean));
398+ } else if (name == " object" ) {
399+ types.set (std::to_underlying (JSON::Type::Object));
400+ } else if (name == " array" ) {
401+ types.set (std::to_underlying (JSON::Type::Array));
402+ } else if (name == " integer" ) {
403+ types.set (std::to_underlying (JSON::Type::Integer));
404+ } else if (name == " string" ) {
405+ types.set (std::to_underlying (JSON::Type::String));
406+ } else if (name == " number" ) {
407+ types.set (std::to_underlying (JSON::Type::Real));
408+ types.set (std::to_underlying (JSON::Type::Integer));
409+ types.set (std::to_underlying (JSON::Type::Decimal));
410+ } else {
411+ return false ;
412+ }
413+ return true ;
414+ }
415+
392416auto is_integer_type_check (const Instruction &instruction) -> bool {
393417 return (instruction.type == InstructionIndex::AssertionType ||
394418 instruction.type == InstructionIndex::AssertionTypeStrict) &&
@@ -2151,13 +2175,83 @@ auto compiler_draft3_validation_type(const Context &context,
21512175 return {};
21522176}
21532177
2154- auto compiler_draft3_validation_disallow (const Context &,
2178+ auto compiler_draft3_validation_disallow (const Context &context ,
21552179 const SchemaContext &schema_context,
2156- const DynamicContext &,
2180+ const DynamicContext &dynamic_context ,
21572181 const Instructions &) -> Instructions {
2158- throw sourcemeta::blaze::CompilerError (
2159- schema_context.base , to_pointer (schema_context.relative_pointer ),
2160- " Draft 3 disallow compilation is not yet implemented" );
2182+ const auto &value{schema_context.schema .at (dynamic_context.keyword )};
2183+
2184+ const auto contains_any{
2185+ (value.is_string () && value.to_string () == " any" ) ||
2186+ (value.is_array () &&
2187+ std::ranges::any_of (value.as_array (), [](const auto &element) {
2188+ return element.is_string () && element.to_string () == " any" ;
2189+ }))};
2190+ if (contains_any) {
2191+ return {make (sourcemeta::blaze::InstructionIndex::AssertionFail, context,
2192+ schema_context, dynamic_context, ValueNone{})};
2193+ }
2194+
2195+ ValueTypes types{};
2196+ Instructions subschema_nots;
2197+
2198+ if (value.is_string ()) {
2199+ draft3_set_type_bits (value.to_string (), types);
2200+ } else if (value.is_array ()) {
2201+ for (std::uint64_t index = 0 ; index < value.size (); index++) {
2202+ const auto &element{value.at (index)};
2203+ if (element.is_string ()) {
2204+ draft3_set_type_bits (element.to_string (), types);
2205+ } else if (element.is_object ()) {
2206+ sourcemeta::core::WeakPointer index_suffix;
2207+ index_suffix.push_back (index);
2208+ const auto element_uri{
2209+ sourcemeta::core::to_uri (
2210+ schema_context.relative_pointer .concat (index_suffix),
2211+ schema_context.base )
2212+ .canonicalize ()
2213+ .recompose ()};
2214+
2215+ auto inner_instructions{
2216+ compile (context, schema_context, relative_dynamic_context (),
2217+ sourcemeta::core::empty_weak_pointer,
2218+ sourcemeta::core::empty_weak_pointer, element_uri)};
2219+
2220+ const auto element_relative_pointer{
2221+ schema_context.relative_pointer .concat (index_suffix)};
2222+ const SchemaContext element_schema_context{
2223+ .relative_pointer = element_relative_pointer,
2224+ .schema = schema_context.schema ,
2225+ .vocabularies = schema_context.vocabularies ,
2226+ .base = schema_context.base ,
2227+ .is_property_name = schema_context.is_property_name };
2228+
2229+ const auto element_base_schema_location{
2230+ sourcemeta::blaze::make_weak_pointer (dynamic_context.keyword ,
2231+ index)};
2232+ const DynamicContext element_dynamic_context{
2233+ .keyword = KEYWORD_EMPTY,
2234+ .base_schema_location = element_base_schema_location,
2235+ .base_instance_location = dynamic_context.base_instance_location };
2236+
2237+ subschema_nots.push_back (
2238+ make (sourcemeta::blaze::InstructionIndex::LogicalNot, context,
2239+ element_schema_context, element_dynamic_context, ValueNone{},
2240+ std::move (inner_instructions)));
2241+ }
2242+ }
2243+ }
2244+
2245+ Instructions result;
2246+ if (types.any ()) {
2247+ result.push_back (
2248+ make (sourcemeta::blaze::InstructionIndex::AssertionNotTypeStrictAny,
2249+ context, schema_context, dynamic_context, types));
2250+ }
2251+ for (auto &&instruction : subschema_nots) {
2252+ result.push_back (std::move (instruction));
2253+ }
2254+ return result;
21612255}
21622256
21632257auto compiler_draft3_applicator_extends (const Context &context,
0 commit comments