from typing import Any
import ast


def value_to_ast_node(value: Any, dtype: type) -> ast.AST:
    """An inverse operation to @ast_node_to_value function. This function takes
    some value (str, int, or nested structures of dicts list etc) and return
    corresponding AST node.

    For example: value=5, dtype=int, this function will return: ast.Num(value)

    Args:
        value: a python variable like: 4, 'text', {'s': 5, 't': [1, 2]}
        dtype: a python type of the value which determines the output type
            of the AST node.

    Returns:
        node: initialized AST node

    Raises:
        ValueError: when the dtype of is not supported
    """
    if value is None:
        return ast.Module(body=str(value))
    elif dtype in [int, float]:
        return ast.Num(value)
    elif dtype == bool:
        return ast.NameConstant(value)
    elif dtype == str:
        return ast.Str(value)
    elif dtype == list:
        return ast.List(elts=[value_to_ast_node(e, type(e)) for e in value])
    elif dtype == tuple:
        return ast.Tuple(elts=[value_to_ast_node(e, type(e)) for e in value])
    elif dtype == dict:
        return ast.Dict(
            keys=[value_to_ast_node(key, type(key)) for key in value.keys()],
            values=[value_to_ast_node(val, type(val)) for val in value.values()],
        )
    elif dtype == type:
        return ast.Module(body=value)
    else:
        raise ValueError(f"Cannot parse value: {value} with dtype: {dtype} to ast Node")