I am trying to access an attribute of a class and get an error that the instance does not have the attribute. My example is a bit more complicated, but I boiled it down to this minimal example:

from artiq.experiment import *

class Foo:
    @portable
    def __init__(self):
        self.bar = 42

class Exp(EnvExperiment):
    def build(self):
        self.setattr_device("core")

    @kernel 
    def run(self):
        foo = Foo()
        x = foo.bar # try to access attribute

Here is the error message:

check.py:15:17-15:20: error: type <instance artiq_run_check.Foo {
                __objectid__: numpy.int32
        }> does not have an attribute 'bar'
        x = foo.bar # try to access attribute
            ~~~ ^^^

I'd expected that foo.bar yields 42. Why do I see the compiler error?

Make it a class attribute with a type.

This is where I actually came from. I initially tried

from artiq.experiment import *

class Foo:
    bar: TInt32 = 0

    @portable
    def __init__(self):
        self.bar = 42

class Exp(EnvExperiment):
    def build(self):
        self.setattr_device("core")

    @kernel 
    def run(self):
        foo = Foo()
        x = foo.bar # try to access attribute

but it yields the same error message.

I also tried a lot of other variations, but with no success so far.

After trying a bit more it seems that this error occurs if the instance of Foo is created in a @kernel function. If I create it for example in build, it works:

class Exp(EnvExperiment):
    def build(self):
        self.setattr_device("core")
        self.foo = Foo()

    @kernel 
    def run(self):
        self.foo.bar

Is this observation correct?

Just as background: I need to communicate with a device over SPI and for that I need to create the right commands. For the bit fiddeling I wrote a small class which contains the actual data (4x TInt64) and some methods that do the bit fiddeling. While it is possible to instantiate instances of this class in build, it is not really elegant but a hack "to get it working".
Is is in general not possible to instantiate instances of classes in a kernel function? Or is there some workaround?

If I understand your application correctly the approach would be to not have a variable number of data classes but either a fixed big dataclass that keeps it's data in arrays (like a variable length but sixed capacity vector). Or alternatively (and faster) do the botfiddling before compile and runtime in your outer build() and then just use arrays.

4 days later

In my case it is not always possible to do the bit fiddeling inbuild. I am now instantiating the bit fiddeling class in build and everything works.

But in general: Is it possible to instantiate simple python classes in a @kernel method?

In C or C++ one often uses structs to group different variables. Often the structs are so small that they easily fit on the stack. My idea was basically the same: Group an array of fixed length with an integer in a class and instantiate the class in a @kernel method.

    MichaelHartmann But in general: Is it possible to instantiate simple python classes in a @kernel method?

    With NAC3 yes, but it is fairly incomplete with the current compiler.