Alexander Ioffe
03/27/2024, 2:12 AMIrLocalDelegatedProperty
? I'm trying to write a visitor that converts something like this:
val x = stuff
To something like this:
val x by MyDelegateValue { stuff }
Tóth István Zoltán
03/27/2024, 3:26 AMAlexander Ioffe
03/27/2024, 3:52 AMval x by MyDelegateValue { stuff }
Is this:
[IrLocalDelegatedProperty] name:x type:kotlin.String flags:val
[IrVariable] (orig:PROPERTY_DELEGATE)name:x$delegate type:<root>.UsingStuff.MyDelegateValue<kotlin.String> [val]
[IrConstructorCall] Fun(<init>):<root>.UsingStuff.MyDelegateValue<kotlin.String> origin=null
<class: T>: kotlin.String
inner: [IrFunctionExpression] type=kotlin.coroutines.SuspendFunction0<kotlin.String> origin=LAMBDA
[IrSimpleFunction] (orig:LOCAL_FUNCTION_FOR_LAMBDA) <anonymous>(): kotlin.String [suspend]
[IrBlockBody]
[IrReturn] type=kotlin.Nothing from='Fun(<anonymous>)'
[IrCall] Fun(stuff) - dispatch=UsingStuff
[IrGetObjectValue] 'CLASS OBJECT name:UsingStuff modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.UsingStuff
[IrSimpleFunction] (orig:DELEGATED_PROPERTY_ACCESSOR) <get-x>(): kotlin.String
[IrBlockBody]
[IrReturn] type=kotlin.Nothing from='Fun(<get-x>)'
[IrCall] Fun(getValue) - dispatch=UsingStuff.MyDelegateValue
[IrGetValue] Var(x$delegate)
t: [IrConst] null: kotlin.Nothing?
property: LOCAL_DELEGATED_PROPERTY_REFERENCE 'val x: kotlin.String by (...)' delegate='Var(x$delegate)' getter='Fun(<get-x>)' setter=null type=kotlin.reflect.KProperty0<kotlin.String> origin=PROPERTY_REFERENCE_FOR_DELEGATE
The above is my person kotlin-ir dumper which actually prints the IR classes. If you prefer the original it is:
LOCAL_DELEGATED_PROPERTY name:x type:kotlin.String flags:val
VAR PROPERTY_DELEGATE name:x$delegate type:<root>.UsingStuff.MyDelegateValue<kotlin.String> [val]
CONSTRUCTOR_CALL 'public constructor <init> (inner: kotlin.coroutines.SuspendFunction0<T of <root>.UsingStuff.MyDelegateValue>) [primary] declared in <root>.UsingStuff.MyDelegateValue' type=<root>.UsingStuff.MyDelegateValue<kotlin.String> origin=null
<class: T>: kotlin.String
inner: FUN_EXPR type=kotlin.coroutines.SuspendFunction0<kotlin.String> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String [suspend]
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.String [suspend] declared in <root>.UsingStuff.testing.<anonymous>'
CALL 'public final fun <get-stuff> (): kotlin.String declared in <root>.UsingStuff' type=kotlin.String origin=GET_PROPERTY
$this: GET_OBJECT 'CLASS OBJECT name:UsingStuff modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.UsingStuff
FUN DELEGATED_PROPERTY_ACCESSOR name:<get-x> visibility:local modality:FINAL <> () returnType:kotlin.String
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun <get-x> (): kotlin.String declared in <root>.UsingStuff.testing.<anonymous>'
CALL 'public final fun getValue (t: T of <root>.UsingStuff.MyDelegateValue?, property: kotlin.reflect.KProperty<*>): T of <root>.UsingStuff.MyDelegateValue [operator] declared in <root>.UsingStuff.MyDelegateValue' type=kotlin.String origin=null
$this: GET_VAR 'val x$delegate: <root>.UsingStuff.MyDelegateValue<kotlin.String> [val] declared in <root>.UsingStuff.testing.<anonymous>' type=<root>.UsingStuff.MyDelegateValue<kotlin.String> origin=null
t: CONST Null type=kotlin.Nothing? value=null
property: LOCAL_DELEGATED_PROPERTY_REFERENCE 'val x: kotlin.String by (...)' delegate='val x$delegate: <root>.UsingStuff.MyDelegateValue<kotlin.String> [val] declared in <root>.UsingStuff.testing.<anonymous>' getter='local final fun <get-x> (): kotlin.String declared in <root>.UsingStuff.testing.<anonymous>' setter=null type=kotlin.reflect.KProperty0<kotlin.String> origin=PROPERTY_REFERENCE_FOR_DELEGATE
Alexander Ioffe
03/27/2024, 3:58 AMirFactory.createLocalDelegatedProperty
? That's almost the same as creating a IrLocalDelegatedPropertyImpl
directly which I can use instead.
> Technically you can simply create a backing field that contains the MyDelegatedValue instance and a getter that uses that instance to get the value.
Can you elaborate? How could I do that?Tóth István Zoltán
03/27/2024, 6:31 AMx
let's call it x$yourdelegate
• initialize the backing field of x$yourdelegate
with MyDelegateValue { stuff }
• replace the getter and setter of x
with:
◦ fetch x$yourdelegate
◦ call the appropriate get/set function
This is quite similar to the delegation above and works basically the same.
Technically it is not necessary for MyDelegateValue
to be a delegation provider. You can call whatever function from the getter and the setter.
This code does something similar, in this case it replaces the delegate with a class function call.
https://github.com/spxbhuhb/z2/blob/041dc0048f675ff388c0b8f7be47878c2b80daaf/z2-ko[…]xion/z2/kotlin/schematic/ir/klass/SchematicPropertyTransform.kt