Exemple #1
0
def _check_iterator_modification(
        target_node: vy_ast.VyperNode,
        search_node: vy_ast.VyperNode) -> Optional[vy_ast.VyperNode]:
    similar_nodes = [
        n for n in search_node.get_descendants(type(target_node))
        if vy_ast.compare_nodes(target_node, n)
    ]

    for node in similar_nodes:
        # raise if the node is the target of an assignment statement
        assign_node = node.get_ancestor((vy_ast.Assign, vy_ast.AugAssign))
        # note the use of get_descendants() blocks statements like
        # self.my_array[i] = x
        if assign_node and node in assign_node.target.get_descendants(
                include_self=True):
            return node

        attr_node = node.get_ancestor(vy_ast.Attribute)
        # note the use of get_descendants() blocks statements like
        # self.my_array[i].append(x)
        if (attr_node is not None
                and node in attr_node.value.get_descendants(include_self=True)
                and attr_node.attr in ("append", "pop", "extend")):
            return node

    return None
Exemple #2
0
def get_type_from_annotation(
    node: vy_ast.VyperNode,
    location: DataLocation,
    is_constant: bool = False,
    is_public: bool = False,
    is_immutable: bool = False,
) -> BaseTypeDefinition:
    """
    Return a type object for the given AST node.

    Arguments
    ---------
    node : VyperNode
        Vyper ast node from the `annotation` member of a `VariableDef` or `AnnAssign` node.

    Returns
    -------
    BaseTypeDefinition
        Type definition object.
    """
    namespace = get_namespace()

    if isinstance(node, vy_ast.Tuple):
        values = node.elements
        types = tuple(
            get_type_from_annotation(v, DataLocation.UNSET) for v in values)
        return TupleDefinition(types)

    try:
        # get id of leftmost `Name` node from the annotation
        type_name = next(
            i.id for i in node.get_descendants(vy_ast.Name, include_self=True))
    except StopIteration:
        raise StructureException("Invalid syntax for type declaration", node)
    try:
        type_obj = namespace[type_name]
    except UndeclaredDefinition:
        suggestions_str = get_levenshtein_error_suggestions(
            type_name, namespace, 0.3)
        raise UnknownType(
            f"No builtin or user-defined type named '{type_name}'. {suggestions_str}",
            node) from None

    if (getattr(type_obj, "_as_array", False)
            and isinstance(node, vy_ast.Subscript)
            and node.value.get("id") != "DynArray"):
        # TODO: handle `is_immutable` for arrays
        # if type can be an array and node is a subscript, create an `ArrayDefinition`
        length = get_index_value(node.slice)
        value_type = get_type_from_annotation(node.value, location,
                                              is_constant, False, is_immutable)
        return ArrayDefinition(value_type, length, location, is_constant,
                               is_public, is_immutable)

    try:
        return type_obj.from_annotation(node, location, is_constant, is_public,
                                        is_immutable)
    except AttributeError:
        raise InvalidType(f"'{type_name}' is not a valid type", node) from None
Exemple #3
0
def _check_iterator_assign(
    target_node: vy_ast.VyperNode, search_node: vy_ast.VyperNode
) -> Optional[vy_ast.VyperNode]:
    similar_nodes = [
        n
        for n in search_node.get_descendants(type(target_node))
        if vy_ast.compare_nodes(target_node, n)
    ]

    for node in similar_nodes:
        # raise if the node is the target of an assignment statement
        assign_node = node.get_ancestor((vy_ast.Assign, vy_ast.AugAssign))
        if assign_node and node in assign_node.target.get_descendants(include_self=True):
            return node

    return None
Exemple #4
0
def get_type_from_annotation(
    node: vy_ast.VyperNode,
    location: DataLocation,
    is_immutable: bool = False,
    is_public: bool = False,
) -> BaseTypeDefinition:
    """
    Return a type object for the given AST node.

    Arguments
    ---------
    node : VyperNode
        Vyper ast node from the `annotation` member of an `AnnAssign` node.

    Returns
    -------
    BaseTypeDefinition
        Type definition object.
    """
    namespace = get_namespace()
    try:
        # get id of leftmost `Name` node from the annotation
        type_name = next(
            i.id for i in node.get_descendants(vy_ast.Name, include_self=True))
    except StopIteration:
        raise StructureException("Invalid syntax for type declaration", node)
    try:
        type_obj = namespace[type_name]
    except UndeclaredDefinition:
        raise UnknownType(
            f"No builtin or user-defined type named '{type_name}'",
            node) from None

    if getattr(type_obj, "_as_array", False) and isinstance(
            node, vy_ast.Subscript):
        # if type can be an array and node is a subscript, create an `ArrayDefinition`
        length = get_index_value(node.slice)
        value_type = get_type_from_annotation(node.value, location,
                                              is_immutable, False)
        return ArrayDefinition(value_type, length, location, is_immutable,
                               is_public)

    try:
        return type_obj.from_annotation(node, location, is_immutable,
                                        is_public)
    except AttributeError:
        raise InvalidType(f"'{type_name}' is not a valid type", node) from None
Exemple #5
0
    def from_annotation(
        cls,
        node: vy_ast.VyperNode,
        location: DataLocation = DataLocation.MEMORY,
        is_immutable: bool = False,
        is_public: bool = False,
    ) -> _ArrayValueDefinition:
        if not isinstance(node, vy_ast.Subscript):
            raise StructureException(
                f"Cannot declare {cls._id} type without a maximum length", node
            )
        if len(node.get_descendants(vy_ast.Subscript, include_self=True)) > 1:
            raise StructureException(f"Multidimensional {cls._id} arrays are not supported", node)
        if node.get("value.id") != cls._id:
            raise UnexpectedValue("Node id does not match type name")

        length = validation.utils.get_index_value(node.slice)  # type: ignore
        return cls._type(length, location, is_immutable, is_public)