| // LANGUAGE: +ContextParameters |
| // TARGET_BACKEND: JVM_IR |
| // IGNORE_BACKEND_K1: ANY |
| // WITH_STDLIB |
| |
| |
| @file:Suppress("RESERVED_VAR_PROPERTY_OF_VALUE_CLASS") |
| |
| open class EntityFactory<E>(val size: Int, val factory: (Int) -> E) |
| |
| class EntityContext { |
| var d = DoubleArray(16) |
| private set |
| var size: Int = 0 |
| private set |
| fun <E> create(entity: EntityFactory<E>): E { |
| val i = size |
| size += entity.size |
| if (size > d.size) d = d.copyOf(maxOf(2 * d.size, size)) |
| return entity.factory(i) |
| } |
| } |
| |
| @JvmInline value class EDouble(private val i: Int) { |
| companion object Factory : EntityFactory<EDouble>(1, ::EDouble) |
| |
| context(context: EntityContext) |
| var value: Double |
| get() = context.d[i] |
| set(value) { context.d[i] = value } |
| } |
| |
| @JvmInline value class EVec3(private val i: Int) { |
| companion object Factory : EntityFactory<EVec3>(3, ::EVec3) |
| |
| context(context: EntityContext) |
| var x: Double |
| get() = context.d[i] |
| set(value) { context.d[i] = value } |
| |
| context(context: EntityContext) |
| var y: Double |
| get() = context.d[i + 1] |
| set(value) { context.d[i + 1] = value } |
| |
| context(context: EntityContext) |
| var z: Double |
| get() = context.d[i + 2] |
| set(value) { context.d[i + 2] = value } |
| } |
| |
| context(context: EntityContext) |
| fun EVec3.str(): String = |
| "[$x, $y, $z]" |
| |
| context(context: EntityContext) |
| operator fun EVec3.plusAssign(v: EVec3) { |
| x += v.x |
| y += v.y |
| z += v.z |
| } |
| |
| fun box(): String = with(EntityContext()) { |
| val v0 = create(EVec3) |
| v0.x = 1.0 |
| v0.y = 2.0 |
| v0.z = 3.0 |
| val v1 = create(EVec3) |
| v1.x = 2.0 |
| v1.y = 0.0 |
| v1.z = 4.0 |
| v1 += v0 |
| if (v1.x == 3.0 && v1.y == 2.0 && v1.z == 7.0) "OK" else "fail" |
| } |