In constructs such as 'd[i] += x', where both indexed get and indexed
set are dynamic calls, it's safe to generate augmented assignment body
directly, without temporary variables for array ('d') and index ('i').
Note that corresponding IntermediateValue's are OnceExpressionValue's,
which would throw an exception if this assumption is violated.
NB1 Not every dynamic unary or binary expression is translated to
dynamic operator expressions literally. For example, assignments and
increments can have safe calls in LHS, which require some extra logic.
NB2 There are some open design questions left regarding how dynamic
expressions should actually be translated.
* if enum class has abstract members, then it is ABSTRACT
* otherwise, if enum class has entries with members, then it is OPEN
* otherwise, it is FINAL.
In super class constructor arguments, 'this' can be resolved
as a reference to a companion object of a superclass.
This breaks an assumption in psi2ir that 'this' can only refer to some
receiver from the current scope.
If 'this' refers to an 'object' (including 'companion obejct'),
and we are not inside the corresponding class scope,
then 'this' represents a reference to a singleton instance "by name"
(represented as IrGetObjectValue).
In the desugaring for compound assignment to a collection element,
argument expression 'i' is mapped to value parameters 'iG' and 'iS' of
corresponding 'get' and 'set' operators.
In general, these value parameters can have different indices.
This requires extra machinery in argument generation - that is, to be
able to generate a particular expression argument using an arbitrary
callback. In the vast majority of the cases this callback will just use
the corresponding StatementGenerator to generate IR subtree for the
provided expression. In case of 'get' and 'set' operator calls for an
augmented assignment expression this will map corresponding argument
expressions to pregenerated temporary variables.
Thus, in the following context:
```
class A
operator fun A.get(vararg xs: Int) = 0
operator fun A.set(i: Int, j: Int, v: Int) {}
```
statement `a[1, 2] += 3` will be desugared as (in a really pseudo
Kotlin):
```
{
val tmp_array = a
val tmp_index0 = 1
val tmp_index1 = 2
tmp_array.set(
i = tmp_index0,
j = tmp_index1,
v = tmp_array.get(xs = [tmp_index0, tmp_index1]).plus(3)
)
}
```