'Creates an Routine object that is appropriate for this language.
This implementation is appropriate for at least C/Fortran.  Subclasses
can override this if necessary.
Here, we assume at most one return value (the l-value) which must be
scalar.  Additional outputs are OutputArguments (e.g., pointers on
right-hand-side or pass-by-reference).  Matrices are always returned
via OutputArguments.  If ``argument_sequence`` is None, arguments will
be ordered alphabetically, but with all InputArguments first, and then
OutputArgument and InOutArguments.'

def routine(self, name, expr, argument_sequence, global_vars):

    if (is_sequence(expr) and (not isinstance(expr, (MatrixBase, MatrixExpr)))):
        if (not expr):
            raise ValueError('No    expression    given')
        expressions = Tuple(*expr)
    else:
        expressions = Tuple(expr)
    local_vars = {i.label for i in expressions.atoms(Idx)}
    global_vars = (set() if (global_vars is None) else set(global_vars))
    symbols = ((expressions.free_symbols - local_vars) - global_vars)
    new_symbols = set([])
    new_symbols.update(symbols)
    for symbol in symbols:
        if isinstance(symbol, Idx):
            new_symbols.remove(symbol)
            new_symbols.update(symbol.args[1].free_symbols)
    symbols = new_symbols
    return_val = []
    output_args = []
    for expr in expressions:
        if isinstance(expr, Equality):
            out_arg = expr.lhs
            expr = expr.rhs
            if isinstance(out_arg, Indexed):
                dims = tuple([(S.Zero, (dim - 1)) for dim in out_arg.shape])
                symbol = out_arg.base.label
            elif isinstance(out_arg, Symbol):
                dims = []
                symbol = out_arg
            elif isinstance(out_arg, MatrixSymbol):
                dims = tuple([(S.Zero, (dim - 1)) for dim in out_arg.shape])
                symbol = out_arg
            else:
                raise CodeGenError('Only    Indexed,    Symbol,    or    MatrixSymbol    can    define    output    arguments.')
            if expr.has(symbol):
                output_args.append(InOutArgument(symbol, out_arg, expr, dimensions=dims))
            else:
                output_args.append(OutputArgument(symbol, out_arg, expr, dimensions=dims))
            symbols.remove(symbol)
        elif isinstance(expr, (ImmutableMatrix, MatrixSlice)):
            out_arg = MatrixSymbol(('out_%s' % abs(hash(expr))), *expr.shape)
            dims = tuple([(S.Zero, (dim - 1)) for dim in out_arg.shape])
            output_args.append(OutputArgument(out_arg, out_arg, expr, dimensions=dims))
        else:
            return_val.append(Result(expr))
    arg_list = []
    array_symbols = {}
    for array in expressions.atoms(Indexed):
        array_symbols[array.base.label] = array
    for array in expressions.atoms(MatrixSymbol):
        array_symbols[array] = array
    for symbol in sorted(symbols, key=str):
        if (symbol in array_symbols):
            dims = []
            array = array_symbols[symbol]
            for dim in array.shape:
                dims.append((S.Zero, (dim - 1)))
            metadata = {'dimensions': dims}
        else:
            metadata = {}
        arg_list.append(InputArgument(symbol, **metadata))
    output_args.sort(key=(lambda x: str(x.name)))
    arg_list.extend(output_args)
    if (argument_sequence is not None):
        new_sequence = []
        for arg in argument_sequence:
            if isinstance(arg, IndexedBase):
                new_sequence.append(arg.label)
            else:
                new_sequence.append(arg)
        argument_sequence = new_sequence
        missing = [x for x in arg_list if (x.name not in argument_sequence)]
        if missing:
            msg = "Argument    list    didn't    specify:    {0}    "
            msg = msg.format(',    '.join([str(m.name) for m in missing]))
            raise CodeGenArgumentListError(msg, missing)
        name_arg_dict = {x.name: x for x in arg_list}
        new_args = []
        for symbol in argument_sequence:
            try:
                new_args.append(name_arg_dict[symbol])
            except KeyError:
                new_args.append(InputArgument(symbol))
        arg_list = new_args
    return Routine(name, arg_list, return_val, local_vars, global_vars)
