Turn a value into ast expression.

    >>> a = 1
    >>> print(ast.dump(to_ast(a)))
    Num(n=1)
    >>> a = [1, 2, 3]
    >>> print(ast.dump(to_ast(a)))
    List(elts=[Num(n=1), Num(n=2), Num(n=3)], ctx=Load())

def to_ast(value):
    """
    Turn a value into ast expression.

    >>> a = 1
    >>> print(ast.dump(to_ast(a)))
    Num(n=1)
    >>> a = [1, 2, 3]
    >>> print(ast.dump(to_ast(a)))
    List(elts=[Num(n=1), Num(n=2), Num(n=3)], ctx=Load())
    """

    if isinstance(value, (type(None), bool)):
        return builtin_folding(value)
    if sys.version_info[0] == 2 and isinstance(value, long):
        from pythran.syntax import PythranSyntaxError
        raise PythranSyntaxError("constant folding results in big int")
    if any(value is t for t in (bool, int, float)):
        iinfo = np.iinfo(int)
        if isinstance(value, int) and not (iinfo.min <= value <= iinfo.max):
            from pythran.syntax import PythranSyntaxError
            raise PythranSyntaxError("constant folding results in big int")
        return builtin_folding(value)
    elif isinstance(value, np.generic):
        return to_ast(np.asscalar(value))
    elif isinstance(value, numbers.Number):
        return ast.Num(value)
    elif isinstance(value, str):
        return ast.Str(value)
    elif isinstance(value, (list, tuple, set, dict, np.ndarray)):
        return size_container_folding(value)
    elif hasattr(value, "__module__") and value.__module__ == "__builtin__":
        # TODO Can be done the same way for others modules
        return builtin_folding(value)
    # only meaningful for python3
    elif sys.version_info.major == 3:
        if isinstance(value, (filter, map, zip)):
            return to_ast(list(value))
    raise ToNotEval()