Skip to content

Instantly share code, notes, and snippets.

@Takhion
Created September 29, 2018 17:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Takhion/ecedfd599357466a43d7ec1ecc3801e5 to your computer and use it in GitHub Desktop.
Save Takhion/ecedfd599357466a43d7ec1ecc3801e5 to your computer and use it in GitHub Desktop.
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