Hi, not sure if this question belongs here, I beli...
# getting-started
w
Hi, not sure if this question belongs here, I believe it to be a general kotlin issue I'm not understanding. I'm using a custom scripting host, but I don't think it's relevant here. If you think it is, let me now and I'll move the question to that channel. The script host uses this as the root object class :
Copy code
open class Pipeline : DeclareContext() {
    val vertexShader = VertexShader()
    val fragmentShader = FragmentShader()

    fun vertexShader(init : VertexShader.() -> Unit) {
        vertexShader.apply(init)
    }

    fun fragmentShader(init : FragmentShader.() -> Unit) {
        fragmentShader.apply(init)
    }
}
and I have this in the script file:
Copy code
val color by declaring(Vec4)
vertexShader {
    val inPosition by input(Vec2)

    // val testUbo by uniform(Vec4)

    position <= vec4(inPosition, 0.0f, 1.0f)
}
The IDE helps me out and confirms that inside the block,
this
is
VertexShader
, i.e not nullable. That call to
input()
is an error when run and the IDE agrees with a red squiggle, because apparently I don't have a matching
provideDelegate
function. The implementation that should apply looks like this:
Copy code
inline operator fun <reified T, U> InputStruct<T>.provideDelegate(thisRef : VertexShader, prop : KProperty<*>) : T where T : StructImpl<T>, T : Expression<U>{
    val struct = this.def.create(prop.name, null)
    if (ref != null) {
        ref.inputs += struct
    } else {
        throw RuntimeException("This block shouldn't bee nullable?")
    }
    return struct
}
It is roughly equivalent to the
provideDelegate
for the return value of the
declaring
in the outer scope, but that one does not complain. The error complains that the
thisRef
of my
provideDelegate
is not nullable. When I make
thisRef
VertexShader?
, it compiles without issue but the
thisRef
passed in is null and I need the
VertexShader
in this case. Am I not understanding something about the semantics around
provideDelegate
or function receivers?
1
The specific error in case that provides any clues:
Copy code
Property delegate must have a 'provideDelegate(Nothing?, KProperty<*>)' method. None of the following functions is suitable: 
public inline operator fun <reified T : StructImpl<Vec2>, U> Shader.InputStruct<Vec2>.provideDelegate(ref: VertexShader, prop: KProperty<*>): Vec2 where T : Expression<IVec2> defined in org.ksentiment.shaderdsl
In true rubber duck fashion, I figured it out after I pulled together my question. The clue was the
Nothing?
expected in the signature. thisRef is only provided when you declare a delegated property on a class. thisRef is
Nothing?
if the delegate is declared anywhere else (function, lambda, etc), even if there is a
this
in the context. The ONLY exception appears to be in a script host, where the root object is treated as a class declaration as well. I was able to work around this by updating the input() method on my Shader such that I put
this
on the object returned, like so:
Copy code
class InputStruct<T : Struct<T>>(val shader : Shader, val def : StructDef<T>)
fun <T : Struct<T>> input(def : StructDef<T>) = InputStruct(this, def)
And then updating the provideDelegate method so that
thisRef : Any?
since I was not going to use it.
🚀 1
y
You could've also used context receivers for this on the provideDelegate method FYI