'Resolve a list of field selectors against this resource
@param selectors: the field selectors
@param skip_components: skip fields in components
@param extra_fields: automatically add extra_fields of all virtual
fields in this table
@param show: default for S3ResourceField.show
@return: tuple of (fields, joins, left, distinct)'

def resolve_selectors(self, selectors, skip_components=False, extra_fields=True, show=True):

    prefix = (lambda s: (('~.%s' % s) if ('.' not in s.split('$', 1)[0]) else s))
    display_fields = set()
    add = display_fields.add
    for item in selectors:
        if (not item):
            continue
        elif (type(item) is tuple):
            item = item[(-1)]
        if isinstance(item, str):
            selector = item
        elif isinstance(item, S3ResourceField):
            selector = item.selector
        elif isinstance(item, FS):
            selector = item.name
        else:
            continue
        add(prefix(selector))
    slist = list(selectors)
    if extra_fields:
        extra = self.get_config('extra_fields')
        if extra:
            append = slist.append
            for selector in extra:
                s = prefix(selector)
                if (s not in display_fields):
                    append(s)
    joins = {}
    left = {}
    distinct = False
    columns = set()
    add_column = columns.add
    rfields = []
    append = rfields.append
    for s in slist:
        if (type(s) is tuple):
            (label, selector) = s
        else:
            (label, selector) = (None, s)
        if isinstance(selector, str):
            selector = prefix(selector)
            try:
                rfield = S3ResourceField(self, selector, label=label)
            except (AttributeError, SyntaxError):
                continue
        elif isinstance(selector, FS):
            try:
                rfield = selector.resolve(self)
            except (AttributeError, SyntaxError):
                continue
        elif isinstance(selector, S3ResourceField):
            rfield = selector
        else:
            continue
        if ((rfield.field is None) and (not rfield.virtual)):
            continue
        colname = rfield.colname
        if (colname in columns):
            continue
        else:
            add_column(colname)
        if (label is not None):
            rfield.label = label
        if skip_components:
            head = rfield.selector.split('$', 1)[0]
            if (('.' in head) and (head.split('.')[0] not in ('~', self.alias))):
                continue
        if rfield.distinct:
            left.update(rfield._joins)
            distinct = True
        elif rfield.join:
            joins.update(rfield._joins)
        rfield.show = (show and (rfield.selector in display_fields))
        append(rfield)
    return (rfields, joins, left, distinct)
