local typeRank = { boolean = 1, number = 2, string = 3, userdata = 4, ['nil'] = math.huge }
local booleanRank = { [false] = 0, [true] = 1 }

function compare(a, b)
    local typea, typeb = type(a), type(b)
    if typea == typeb then
        if a == b then
            return 0
        end
        if typea == 'boolean' then
            return booleanRank[a] - booleanRank[b]
        elseif typea == 'number' then
            return a - b
        elseif typea == 'string' then
            local A, B = string.upper(a), string.upper(b)
            if A < B then
                return -1
            elseif A > B then
                return 1
            elseif a < b then
                return -1
            elseif a > b then
                return 1
            end
            return 0
        elseif typea == 'userdata' then
            if a.__eq and a.__eq == b.__eq then
                if a < b then
                    return -1
                elseif a > b then
                    return 1
                end
            end
            return 0
        end
    else
        return typeRank[typea] - typeRank[typeb]
    end
end

return compare
