示例#1
0
def for_header_to_tuple(
        target, target_type,
        iter_) -> t.Tuple[typed_ast3.Assign, typed_ast3.AST, typed_ast3.AST]:
    if match_range_call(iter_):
        begin, end, step = inferred_range_args(iter_)
        # raise NotImplementedError('TODO')
    else:
        raise NotImplementedError(
            'only range() iterator in for loops is currently supported')

    if target_type is None:
        init = typed_ast3.Assign(targets=[target],
                                 value=begin,
                                 type_comment=None)
    else:
        init = typed_ast3.AnnAssign(target=target,
                                    annotation=target_type,
                                    value=begin,
                                    simple=True)
    condition = typed_ast3.Compare(left=target,
                                   ops=[typed_ast3.Lt()],
                                   comparators=[end])
    increment = typed_ast3.AugAssign(target=target,
                                     op=typed_ast3.Add(),
                                     value=step)
    return init, condition, increment
示例#2
0
    def visit_Assign(self, node):
        #astpretty.pprint(node)
        #Assign(expr* targets, expr value)
        #AnnAssign(expr target, expr annotation, expr? value, int simple)

        res = node
        targets, value = node.targets, node.value
        lineno = node.lineno
        if lineno in self.line2shape:
            assert len(targets) == 1
            target = targets[0]
            shape = self.line2shape[lineno]
            ann = ast.Str(s=f'{shape}',
                          kind='',
                          lineno=lineno,
                          col_offset=node.col_offset)
            #print("\n===>", astpretty.pprint(node, indent=' '))
            res = ast.AnnAssign(target=target,
                                annotation=ann,
                                value=value,
                                simple=1,
                                lineno=lineno,
                                col_offset=node.col_offset)

        return res
示例#3
0
 def visit_node(self, node):
     if isinstance(node, typed_ast3.For) and node.target.id == var \
             and node.type_comment is not None:
         node.type_comment = None
         declaration = typed_ast3.AnnAssign(
             target=node.target, value=None, annotation=node.resolved_type_comment)
         raise ValueError(declaration)
示例#4
0
 def visit_Decl(self, node) -> t.Union[typed_ast3.AnnAssign,  # pylint: disable=invalid-name
                                       t.Tuple[str, typed_ast3.arguments, typed_ast3.AST]]:
     """Transform Decl."""
     name = node.name
     assert isinstance(name, str), type(name)
     quals = node.quals
     if quals:
         _LOG.warning('ignoring unsupported C grammar: %s', quals)
     storage = [self.visit(subnode) for subnode in node.storage]
     if storage:
         raise NotImplementedError(_node_debug(node.storage), str(storage))
     funcspec = [self.visit(subnode) for subnode in node.funcspec]
     if funcspec:
         raise NotImplementedError(_node_debug(node.funcspec), str(funcspec))
     type_data = self.visit(node.type)
     assert isinstance(type_data, tuple)
     assert len(type_data) == DECL_DATA_LENGTHS[type(node.type)], (type(node.type), type_data)
     init = self.visit(node.init)
     if init is not None:
         assert isinstance(node.type, INITIALIZABLE_DECLARATIONS)
         # assert isinstance(node.type, c_ast.TypeDecl), type(node.type)
         # raise NotImplementedError(_node_debug(node.init), str(init))
     bitsize = self.visit(node.bitsize)
     if bitsize is not None:
         raise NotImplementedError(_node_debug(node.bitsize), str(bitsize))
     _ = self.visit(node.coord)
     if init is not None or isinstance(node.type, INITIALIZABLE_DECLARATIONS):
         name_, type_ = type_data
         assert name_ == name
         return typed_ast3.AnnAssign(target=typed_ast3.Name(id=name_, ctx=typed_ast3.Store()),
                                     annotation=type_, value=init, simple=1)
     if isinstance(node.type, (c_ast.FuncDecl,)):
         return type_data
     return self.generic_visit(node)
示例#5
0
 def visit_Typedef(self, node):  # pylint: disable=invalid-name
     """Transform Typedef."""
     name = node.name
     assert isinstance(name, str), type(name)
     quals = node.quals
     if quals:
         _LOG.warning('ignoring unsupported C grammar: %s', quals)
     assert node.storage == ['typedef'], node.storage
     name_, type_ = self.visit(node.type)
     assert name == name_, (name, name_)
     _ = self.visit(node.coord)
     return typed_ast3.AnnAssign(target=typed_ast3.Name(name, typed_ast3.Store()), value=type_,
                                 annotation=typed_ast3.Name('type', typed_ast3.Load()), simple=1)
示例#6
0
def _r_assign(assign, body):
    assert body.type in (syms.file_input, syms.suite)

    if len(assign.targets) != 1:
        # Type aliases and old-style var type comments cannot have multiple
        # targets.
        return []

    if assign.type_comment:
        # old-style variable type comment, let's treat it exactly like
        # a new-style annotated assignment
        tc = parse_type_comment(assign.type_comment)
        annassign = ast3.AnnAssign(
            target=assign.targets[0],
            annotation=tc,
            value=assign.value,
            simple=False,
        )
        return reapply(annassign, body)

    if not isinstance(assign.targets[0], ast3.Name):
        # Type aliases cannot be attributes, etc.
        return []

    name = assign.targets[0].id
    value = convert_annotation(assign.value)
    value.prefix = " "

    for child in flatten_some(body.children):
        if child.type != syms.simple_stmt:
            continue

        maybe_expr = child.children[0]
        if maybe_expr.type != syms.expr_stmt:
            continue

        expr = maybe_expr.children

        if (isinstance(expr[0], Leaf) and expr[0].type == token.NAME
                and expr[0].value == name and expr[1] == _eq):
            actual_value = expr[2]
            if value != actual_value:
                value_str = minimize_whitespace(str(value))
                actual_value_str = minimize_whitespace(str(actual_value))
                raise ValueError(
                    f"incompatible existing alias {name!r}. Expected: " +
                    f"{value_str!r}, actual: {actual_value_str!r}")

            break
    else:
        # We need to defer placing aliases because we need to place them
        # relative to their usage, and the type annotations likely come after
        # in the .pyi file.

        def lazy_aliasing() -> None:
            # We should find the first place where the alias is used and put it
            # right above.  This way we don't need to look at the value at all.
            _, prefix = get_offset_and_prefix(body, skip_assignments=True)
            name_node = Leaf(token.NAME, name)
            for _offset, stmt in enumerate(body.children):
                if name_used_in_node(stmt, name_node):
                    break
            else:
                _offset = -1

            body.children.insert(
                _offset,
                Node(
                    syms.simple_stmt,
                    [
                        Node(
                            syms.expr_stmt,
                            [
                                Leaf(token.NAME, name),
                                new(_eq),
                                value,
                            ],
                        ),
                        new(_newline),
                    ],
                    prefix=prefix.lstrip('\n'),
                ),
            )

        return [lazy_aliasing]

    return []