mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 12:12:45 +00:00 
			
		
		
		
	LibIDL+LibWeb: Resolve distinguishing argument index at build time
Aside from the obvious performance benefits, this will allow us to properly handle dictionary types. (whose dictionary-ness is only known at build-time) Much of the rest of the overload resolution algorithm steps can (and should) be evaluated at build-time as well, but this is a good first step.
This commit is contained in:
		
							parent
							
								
									048e179572
								
							
						
					
					
						commit
						f837f02eea
					
				
					 4 changed files with 44 additions and 43 deletions
				
			
		|  | @ -1925,7 +1925,7 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@@overload_suffi | |||
| } | ||||
| 
 | ||||
| // https://webidl.spec.whatwg.org/#compute-the-effective-overload-set
 | ||||
| static EffectiveOverloadSet compute_the_effective_overload_set(auto const& overload_set) | ||||
| static Vector<EffectiveOverloadSet::Item> compute_the_effective_overload_set(auto const& overload_set) | ||||
| { | ||||
|     // 1. Let S be an ordered set.
 | ||||
|     Vector<EffectiveOverloadSet::Item> overloads; | ||||
|  | @ -2048,7 +2048,7 @@ static EffectiveOverloadSet compute_the_effective_overload_set(auto const& overl | |||
|         overload_id++; | ||||
|     } | ||||
| 
 | ||||
|     return EffectiveOverloadSet { move(overloads) }; | ||||
|     return overloads; | ||||
| } | ||||
| 
 | ||||
| static DeprecatedString generate_constructor_for_idl_type(Type const& type) | ||||
|  | @ -2090,6 +2090,30 @@ static DeprecatedString generate_constructor_for_idl_type(Type const& type) | |||
|     VERIFY_NOT_REACHED(); | ||||
| } | ||||
| 
 | ||||
| // https://webidl.spec.whatwg.org/#dfn-distinguishing-argument-index
 | ||||
| static size_t resolve_distinguishing_argument_index(Vector<EffectiveOverloadSet::Item> const& items, size_t argument_count) | ||||
| { | ||||
|     for (auto argument_index = 0u; argument_index < argument_count; ++argument_index) { | ||||
|         bool found_indistinguishable = false; | ||||
| 
 | ||||
|         for (auto first_item_index = 0u; first_item_index < items.size(); ++first_item_index) { | ||||
|             for (auto second_item_index = first_item_index + 1; second_item_index < items.size(); ++second_item_index) { | ||||
|                 if (!items[first_item_index].types[argument_index]->is_distinguishable_from(items[second_item_index].types[argument_index])) { | ||||
|                     found_indistinguishable = true; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             if (found_indistinguishable) | ||||
|                 break; | ||||
|         } | ||||
| 
 | ||||
|         if (!found_indistinguishable) | ||||
|             return argument_index; | ||||
|     } | ||||
| 
 | ||||
|     VERIFY_NOT_REACHED(); | ||||
| } | ||||
| 
 | ||||
| static void generate_overload_arbiter(SourceGenerator& generator, auto const& overload_set, DeprecatedString const& class_name) | ||||
| { | ||||
|     auto function_generator = generator.fork(); | ||||
|  | @ -2102,8 +2126,7 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@) | |||
|     Optional<IDL::EffectiveOverloadSet> effective_overload_set; | ||||
| )~~~"); | ||||
| 
 | ||||
|     auto all_possible_effective_overloads = compute_the_effective_overload_set(overload_set); | ||||
|     auto overloads_set = all_possible_effective_overloads.items(); | ||||
|     auto overloads_set = compute_the_effective_overload_set(overload_set); | ||||
|     auto maximum_argument_count = 0u; | ||||
|     for (auto const& overload : overloads_set) | ||||
|         maximum_argument_count = max(maximum_argument_count, overload.types.size()); | ||||
|  | @ -2115,29 +2138,28 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@) | |||
|     // Namely, since that discards any overloads that don't have the exact number of arguments that were given,
 | ||||
|     // we simply only provide the overloads that do have that number of arguments.
 | ||||
|     for (auto argument_count = 0u; argument_count <= maximum_argument_count; ++argument_count) { | ||||
|         // FIXME: Calculate the distinguishing argument index now instead of at runtime.
 | ||||
| 
 | ||||
|         auto effective_overload_count = 0; | ||||
|         Vector<EffectiveOverloadSet::Item> effective_overload_set; | ||||
|         for (auto const& overload : overloads_set) { | ||||
|             if (overload.types.size() == argument_count) | ||||
|                 effective_overload_count++; | ||||
|                 effective_overload_set.append(overload); | ||||
|         } | ||||
| 
 | ||||
|         if (effective_overload_count == 0) | ||||
|         if (effective_overload_set.size() == 0) | ||||
|             continue; | ||||
| 
 | ||||
|         auto distinguishing_argument_index = 0u; | ||||
|         if (effective_overload_set.size() > 1) | ||||
|             distinguishing_argument_index = resolve_distinguishing_argument_index(effective_overload_set, argument_count); | ||||
| 
 | ||||
|         function_generator.set("current_argument_count", DeprecatedString::number(argument_count)); | ||||
|         function_generator.set("overload_count", DeprecatedString::number(effective_overload_count)); | ||||
|         function_generator.set("overload_count", DeprecatedString::number(effective_overload_set.size())); | ||||
|         function_generator.appendln(R"~~~( | ||||
|     case @current_argument_count@: { | ||||
|         Vector<IDL::EffectiveOverloadSet::Item> overloads; | ||||
|         overloads.ensure_capacity(@overload_count@); | ||||
| )~~~"); | ||||
| 
 | ||||
|         for (auto& overload : overloads_set) { | ||||
|             if (overload.types.size() != argument_count) | ||||
|                 continue; | ||||
| 
 | ||||
|         for (auto& overload : effective_overload_set) { | ||||
|             StringBuilder types_builder; | ||||
|             types_builder.append("Vector<NonnullRefPtr<IDL::Type const>> { "sv); | ||||
|             StringBuilder optionality_builder; | ||||
|  | @ -2175,8 +2197,9 @@ JS_DEFINE_NATIVE_FUNCTION(@class_name@::@function.name:snakecase@) | |||
|             function_generator.appendln("        overloads.empend(@overload.callable_id@, @overload.types@, @overload.optionality_values@);"); | ||||
|         } | ||||
| 
 | ||||
|         function_generator.set("overload_set.distinguishing_argument_index", DeprecatedString::number(distinguishing_argument_index)); | ||||
|         function_generator.append(R"~~~( | ||||
|         effective_overload_set.emplace(move(overloads)); | ||||
|         effective_overload_set.emplace(move(overloads), @overload_set.distinguishing_argument_index@); | ||||
|         break; | ||||
|     } | ||||
| )~~~"); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Idan Horowitz
						Idan Horowitz