Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle class constructor #2730

Open
Thirumalai-Shaktivel opened this issue Jun 12, 2024 · 13 comments
Open

Handle class constructor #2730

Thirumalai-Shaktivel opened this issue Jun 12, 2024 · 13 comments

Comments

@Thirumalai-Shaktivel
Copy link
Collaborator

from lpython import i32

class test:
    y: i32 = 2
    def __init__(self, x: i32 = 1):
        self.x: i32 = x

t1: test = test()
t2: test = test(3)
print (t1.x)
print (t1.y)
print (t2.x)
print (t2.y)

I think we can skip the __init__()
It has to be represented as a StructTypeConstructor, the class_constructor will take care of the rest.

@Thirumalai-Shaktivel
Copy link
Collaborator Author

Assign: @tanay-man

@Thirumalai-Shaktivel
Copy link
Collaborator Author

Thirumalai-Shaktivel commented Jun 12, 2024

Let's do this.

from lpython import i32, TypeVar

test = TypeVar("test")
class test:
    x: i32 = 0
    y: i32 = 0
    def __init__(self: test, x: i32, y: i32):
        self.x: i32 = x
        self.y: i32 = y

# StrucTypeConstrutor(3, 3)

t2: test = test(3, 3)

@Thirumalai-Shaktivel
Copy link
Collaborator Author

Another example:

from lpython import i32, TypeVar

test = TypeVar("test")
class test:
    kind: str = "abc"
    def __init__(self: test, name: str):
        self.name = name

t1: test = test("1")
t2: test = test("2")

print(t1.kind)
print(t2.kind)

t2.kind = "d"
print(t1.kind)
print(t2.kind)

print(t1.name)
print(t2.name)

@certik
Copy link
Contributor

certik commented Jun 23, 2024

Instead of:

from lpython import i32, TypeVar

test = TypeVar("test")
class test:
    x: i32 = 0
    y: i32 = 0
    def __init__(self: test, x: i32, y: i32):
        self.x: i32 = x
        self.y: i32 = y

# StrucTypeConstrutor(3, 3)

t2: test = test(3, 3)

I recommend doing this:

from lpython import i32, TypeVar

test = TypeVar("test")
class test:
    def __init__(self: test, x: i32, y: i32):
        self.x: i32 = x
        self.y: i32 = y

# StrucTypeConstrutor(3, 3)

t2: test = test(3, 3)

The first are class variables, the second are instance variables. Let's focus on instance variables first.

@tanay-man
Copy link
Contributor

tanay-man commented Jun 24, 2024

The TypeVar is causing conflicts in the symbol table as both the Struct and TypeVar have the same names.

@certik
Copy link
Contributor

certik commented Jun 24, 2024

I think we should have just one "test" in the symbol table, which represents the class definition, it will be of type Struct.

And the corresponding StructType will be the type of the first argument self.

@tanay-man
Copy link
Contributor

I agree the problem is since TypeVar has the same name, we cannot add Struct (class definition) to the symbol table.

@certik
Copy link
Contributor

certik commented Jun 24, 2024

What does LPython currently put into the symbol table for test = TypeVar("test")?

It seems it should just keep note of this variable internally in AST->ASR, but not expose it in ASR. The test variable will be only put into the symbol table once the class test is processed. The test = TypeVar("test") line is just a crutch that we use to make it work with CPython.

@tanay-man
Copy link
Contributor

What does LPython currently put into the symbol table for test = TypeVar("test")?

ASR before adding the Struct node :

(TranslationUnit
    (SymbolTable
        1
        {
            __main__:
                (Module
                    (SymbolTable
                        2
                        {
                            test:
                                (Variable
                                    2
                                    test
                                    []
                                    Local
                                    ()
                                    ()
                                    Default
                                    (TypeParameter
                                        test
                                    )
                                    ()
                                    Source
                                    Public
                                    Required
                                    .false.
                                )
                        })
                    __main__
                    []
                    .false.
                    .false.
                ),
            main_program:
                (Program
                    (SymbolTable
                        5
                        {
                            
                        })
                    main_program
                    []
                    []
                )
        })
    []
)

@certik
Copy link
Contributor

certik commented Jun 25, 2024

I see, the test = TypeVar("test") is a Variable of type TypeParameter which is used for templates. Then in CPython this test gets shadowed. We could shadow it the same way. But why not use the simpler:

class test:
    def __init__(self: "test", x: i32, y: i32):
        self.x: i32 = x
        self.y: i32 = y

@Thirumalai-Shaktivel
Copy link
Collaborator Author

self would of type: TypeParameter or Class or Struct??

@tanay-man
Copy link
Contributor

tanay-man commented Jun 26, 2024

Can we treat self as a special argument? Whenever a function is declared inside a class, it can either have no arguments (if it's a static method) or at least one argument. We can assume the first argument to be a pointer to the object, and therefore, of the type of the class. Can we exempt the first argument from the type annotation requirement? We can treat self as this in lfortran.

@Thirumalai-Shaktivel
Copy link
Collaborator Author

@tanay-man is suggesting the following example:

class test:
  def __init__(self, x: i32, y: i32):
    ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants