-
-
Save Takhion/ecedfd599357466a43d7ec1ecc3801e5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface UserProvider { | |
val user: User | |
} | |
interface User: UserProvider { | |
override val user get() = this | |
fun replaceOperand(from: Value, to: Value) | |
} | |
fun UserProvider.replaceOperand(from: Value, to: Value) = | |
user.replaceOperand(from, to) | |
interface ConstUserProvider: UserProvider { | |
override val user: ConstUser | |
fun ConstUserProvider.operand(value: Value) = | |
ConstUser.OperandDelegate(value) | |
} | |
open class ConstUser(operandCount: Int) : User, ConstUserProvider { | |
override val user get() = this | |
private val operands = arrayOfNulls<Value>(operandCount) | |
override fun replaceOperand(from: Value, to: Value) { | |
for (i in operands.indices) | |
if (operands[i] == from) | |
operands[i] = to | |
from.users -= this | |
} | |
private var nextIndex = 0 | |
class OperandDelegate(private val value: Value) { | |
operator fun provideDelegate( | |
thisRef: ConstUserProvider, | |
prop: KProperty<*> | |
): ReadWriteProperty<ConstUserProvider, Value> { | |
val provideUser = thisRef.user | |
val index = provideUser.nextIndex++ | |
provideUser.operands[index] = value | |
value.users += provideUser | |
return object : ReadWriteProperty<ConstUserProvider, Value> { | |
override fun getValue(thisRef: ConstUserProvider, property: KProperty<*>): Value = | |
thisRef.user.operands[index]!! | |
override fun setValue(thisRef: ConstUserProvider, property: KProperty<*>, value: Value) { | |
val user = thisRef.user | |
user.operands[index]?.users?.remove(provideUser) | |
user.operands[index] = value | |
value.users += provideUser | |
} | |
} | |
} | |
} | |
} | |
abstract class Value { | |
val users = mutableSetOf<User>() | |
fun replaceWith(other: Value) { | |
for (user in users.toSet()) { | |
user.replaceOperand(this, other) | |
} | |
assert(users.isEmpty()) | |
} | |
} | |
class Constant(val value: Int) : Value() | |
abstract class Instruction : Value(), UserProvider | |
// a basic instruction with a constant amount of operands | |
class Add(left: Value, right: Value) : Instruction(), ConstUserProvider by ConstUser(2) { | |
var left by operand(left) | |
var right by operand(right) | |
} | |
// an example of an instruction with a variable amount of operands | |
class MultiAdd(val values: MutableList<Value>) : Instruction(), User { | |
override fun replaceOperand(from: Value, to: Value) { | |
values.replaceAll { if (it == from) to else it } | |
from.users -= this | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment