docs: def spec_update_sourcepath_filter_loaderplugins(
          spec, sourcepath_map, sourcepath_map_key,
          loaderplugin_sourcepath_map_key=LOADERPLUGIN_SOURCEPATH_MAPS):
      """
      Take an existing spec and a sourcepath mapping (that could be
      produced via calmjs.dist.*_module_registry_dependencies functions)
      and split out the keys that does not contain loaderplugin syntax and
      assign it to the spec under sourcepath_key.
  
      For the parts with loader plugin syntax (i.e. modnames (keys) that
      contain a '!' character), they are instead stored under a different
      mapping under its own mapping identified by the plugin_name.  The
      mapping under loaderplugin_sourcepath_map_key will contain all
      mappings of this type.
  
      The resolution for the handlers will be done through the loader
      plugin registry provided via spec[CALMJS_LOADERPLUGIN_REGISTRY] if
      available, otherwise the registry instance will be acquired through
      the main registry using spec[CALMJS_LOADERPLUGIN_REGISTRY_NAME].
  
      For the example sourcepath_map input:
  
      sourcepath = {
          'module': 'something',
          'plugin!inner': 'inner',
          'plugin!other': 'other',
          'plugin?query!question': 'question',
          'plugin!plugin2!target': 'target',
      }
  
      The following will be stored under the following keys in spec:
  
      spec[sourcepath_key] = {
          'module': 'something',
      }
  
      spec[loaderplugin_sourcepath_map_key] = {
          'plugin': {
              'plugin!inner': 'inner',
              'plugin!other': 'other',
              'plugin?query!question': 'question',
              'plugin!plugin2!target': 'target',
          },
      }
  
      The goal of this function is to aid in processing each of the plugin
      types by batch, one level at a time.  It is up to the handler itself
      to trigger further lookups as there are implementations of loader
      plugins that do not respect the chaining mechanism, thus a generic
      lookup done at once may not be suitable.
  
      Note that nested/chained loaderplugins are not immediately grouped
      as they must be individually handled given that the internal syntax
      are generally proprietary to the outer plugin.  The handling will be
      dealt with at the Toolchain.compile_loaderplugin_entry method
      through the associated handler call method.
  
      Toolchain implementations may either invoke this directly as part
      of the prepare step on the required sourcepaths values stored in the
      spec, or implement this at a higher level before invocating the
      toolchain instance with the spec.
      """
  
      default = dict_setget_dict(spec, sourcepath_map_key)
      registry = spec_update_loaderplugin_registry(spec)
  
      # it is more loaderplugin_sourcepath_maps
      plugins = dict_setget_dict(spec, loaderplugin_sourcepath_map_key)
  
      for modname, sourcepath in sourcepath_map.items():
          parts = modname.split('!', 1)
          if len(parts) == 1:
              # default
              default[modname] = sourcepath
              continue
  
          # don't actually do any processing yet.
          plugin_name = registry.to_plugin_name(modname)
          plugin = dict_setget_dict(plugins, plugin_name)
          plugin[modname] = sourcepath