Esempio n. 1
0
def transform_assignment_stmt(builder: IRBuilder,
                              stmt: AssignmentStmt) -> None:
    assert len(stmt.lvalues) >= 1
    builder.disallow_class_assignments(stmt.lvalues, stmt.line)
    lvalue = stmt.lvalues[0]
    if stmt.type and isinstance(stmt.rvalue, TempNode):
        # This is actually a variable annotation without initializer. Don't generate
        # an assignment but we need to call get_assignment_target since it adds a
        # name binding as a side effect.
        builder.get_assignment_target(lvalue, stmt.line)
        return

    # multiple assignment
    if (isinstance(lvalue, TupleExpr) and isinstance(stmt.rvalue, TupleExpr)
            and len(lvalue.items) == len(stmt.rvalue.items)):
        temps = []
        for right in stmt.rvalue.items:
            rvalue_reg = builder.accept(right)
            temp = builder.alloc_temp(rvalue_reg.type)
            builder.assign(temp, rvalue_reg, stmt.line)
            temps.append(temp)
        for (left, temp) in zip(lvalue.items, temps):
            assignment_target = builder.get_assignment_target(left)
            builder.assign(assignment_target, temp, stmt.line)
        return

    line = stmt.rvalue.line
    rvalue_reg = builder.accept(stmt.rvalue)
    if builder.non_function_scope() and stmt.is_final_def:
        builder.init_final_static(lvalue, rvalue_reg)
    for lvalue in stmt.lvalues:
        target = builder.get_assignment_target(lvalue)
        builder.assign(target, rvalue_reg, line)
Esempio n. 2
0
def transform_operator_assignment_stmt(builder: IRBuilder, stmt: OperatorAssignmentStmt) -> None:
    """Operator assignment statement such as x += 1"""
    builder.disallow_class_assignments([stmt.lvalue], stmt.line)
    target = builder.get_assignment_target(stmt.lvalue)
    target_value = builder.read(target, stmt.line)
    rreg = builder.accept(stmt.rvalue)
    # the Python parser strips the '=' from operator assignment statements, so re-add it
    op = stmt.op + '='
    res = builder.binary_op(target_value, rreg, op, stmt.line)
    # usually operator assignments are done in-place
    # but when target doesn't support that we need to manually assign
    builder.assign(target, res, res.line)
Esempio n. 3
0
def transform_assignment_stmt(builder: IRBuilder, stmt: AssignmentStmt) -> None:
    assert len(stmt.lvalues) >= 1
    builder.disallow_class_assignments(stmt.lvalues, stmt.line)
    lvalue = stmt.lvalues[0]
    if stmt.type and isinstance(stmt.rvalue, TempNode):
        # This is actually a variable annotation without initializer. Don't generate
        # an assignment but we need to call get_assignment_target since it adds a
        # name binding as a side effect.
        builder.get_assignment_target(lvalue, stmt.line)
        return

    line = stmt.rvalue.line
    rvalue_reg = builder.accept(stmt.rvalue)
    if builder.non_function_scope() and stmt.is_final_def:
        builder.init_final_static(lvalue, rvalue_reg)
    for lvalue in stmt.lvalues:
        target = builder.get_assignment_target(lvalue)
        builder.assign(target, rvalue_reg, line)
Esempio n. 4
0
def transform_operator_assignment_stmt(builder: IRBuilder, stmt: OperatorAssignmentStmt) -> None:
    """Operator assignment statement such as x += 1"""
    builder.disallow_class_assignments([stmt.lvalue], stmt.line)
    if (is_tagged(builder.node_type(stmt.lvalue))
            and is_tagged(builder.node_type(stmt.rvalue))
            and stmt.op in int_borrow_friendly_op):
        can_borrow = (is_borrow_friendly_expr(builder, stmt.rvalue)
                      and is_borrow_friendly_expr(builder, stmt.lvalue))
    else:
        can_borrow = False
    target = builder.get_assignment_target(stmt.lvalue)
    target_value = builder.read(target, stmt.line, can_borrow=can_borrow)
    rreg = builder.accept(stmt.rvalue, can_borrow=can_borrow)
    # the Python parser strips the '=' from operator assignment statements, so re-add it
    op = stmt.op + '='
    res = builder.binary_op(target_value, rreg, op, stmt.line)
    # usually operator assignments are done in-place
    # but when target doesn't support that we need to manually assign
    builder.assign(target, res, res.line)
Esempio n. 5
0
def transform_assignment_stmt(builder: IRBuilder,
                              stmt: AssignmentStmt) -> None:
    lvalues = stmt.lvalues
    assert len(lvalues) >= 1
    builder.disallow_class_assignments(lvalues, stmt.line)
    first_lvalue = lvalues[0]
    if stmt.type and isinstance(stmt.rvalue, TempNode):
        # This is actually a variable annotation without initializer. Don't generate
        # an assignment but we need to call get_assignment_target since it adds a
        # name binding as a side effect.
        builder.get_assignment_target(first_lvalue, stmt.line)
        return

    # Special case multiple assignments like 'x, y = e1, e2'.
    if (isinstance(first_lvalue, (TupleExpr, ListExpr))
            and isinstance(stmt.rvalue, (TupleExpr, ListExpr))
            and len(first_lvalue.items) == len(stmt.rvalue.items)
            and all(is_simple_lvalue(item)
                    for item in first_lvalue.items) and len(lvalues) == 1):
        temps = []
        for right in stmt.rvalue.items:
            rvalue_reg = builder.accept(right)
            temp = Register(rvalue_reg.type)
            builder.assign(temp, rvalue_reg, stmt.line)
            temps.append(temp)
        for (left, temp) in zip(first_lvalue.items, temps):
            assignment_target = builder.get_assignment_target(left)
            builder.assign(assignment_target, temp, stmt.line)
        return

    line = stmt.rvalue.line
    rvalue_reg = builder.accept(stmt.rvalue)
    if builder.non_function_scope() and stmt.is_final_def:
        builder.init_final_static(first_lvalue, rvalue_reg)
    for lvalue in lvalues:
        target = builder.get_assignment_target(lvalue)
        builder.assign(target, rvalue_reg, line)