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)
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)
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)
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)
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)