Skip to content

Accessing Attributes of Subclasses #791

@01110011011101010110010001101111

Description

Hello! I'm trying to access attributes of subclasses. For example, I'm trying to run something like this:

@dataclass
class Statement:
    pass

@dataclass
class Block(Statement):
    bodies: list[str]

@dataclass
class Assign(Statement):
    var: str
    val: Statement

@dataclass
class Function:
    name: str
    body: Statement

func_body = Block(bodies=["a = 1", "return a"])

test = Function(
        name="foo", 
        body=func_body
)

v1 = test.body

if isinstance(v1, Block):
    bodies = v1.bodies
    if bodies is not None:
        for stmt in bodies:
            print(stmt)
    else:
        print("fail")

For the above example, if the body attribute of the Function class is a Block, I want to be able to iterate through the values in its bodies attribute. The above fails with codon_experiments.py:39 (14-23): error: 'Statement' object has no attribute 'bodies'.

I instead tried to use a Union with NoneType in the parent class:

@dataclass
class Statement:
    bodies: list[str] | NoneType = None
    var: str | NoneType = None
    val: Statement | NoneType = None

@dataclass
class Block(Statement):
    bodies: list[str] | NoneType

@dataclass
class Assign(Statement):
    var: str | NoneType
    val: Statement | NoneType

@dataclass
class Function:
    name: str
    body: Statement

func_body = Block(bodies=["a = 1", "return a"])

test = Function(
        name="foo", 
        body=func_body
)

v1 = test.body

if isinstance(v1, Block):
    bodies = v1.bodies
    if bodies is not None:
        for stmt in bodies:
            print(stmt)
    else:
        print("fail")

The above, however, fails with:

Assert failed:  union already sealed [core.codon:237:1]
Expression:     !isSealed()
Source:         /github/workspace/codon/parser/ast/types/union.cpp:107
Aborted (core dumped)

Finally, I tried to use the Optional type but this resulted in the value always being None:

@dataclass
class Statement:
    bodies: Optional[list[str]] = None
    var: Optional[str] = None
    val: Optional[Statement] = None

@dataclass
class Block(Statement):
    bodies: Optional[list[str]]

@dataclass
class Assign(Statement):
    var: Optional[str]
    val: Optional[Statement]

@dataclass
class Function:
    name: str
    body: Statement

func_body = Block(bodies=["a = 1", "return a"])

test = Function(
        name="foo", 
        body=func_body
)

v1 = test.body

if isinstance(v1, Block):
    bodies = v1.bodies
    if bodies is not None:
        for stmt in bodies:
            print(stmt)
    else:
        print("fail")

The above compiles and runs but always prints fail.

Do you have any suggestions on how to approach this? Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions