-
Notifications
You must be signed in to change notification settings - Fork 170
CPython allows uninitialized variable, LPython does not ? #1991
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
Comments
Hm, I just discussed this precise issue yesterday with our team, I thought it's ok, but I can now see it's not. Here is the example: @dataclass
class ReRange:
start_char_ord : i32
end_char_ord : i32
def check_re_range_alternatives(
alts : list[ReRange],
char : str) -> bool:
result : bool = False
rr : ReRange
for rr in alts:
if check_re_range(rr, char):
result = True
break
return result It gives: semantic error: `rr` must be initialized with an instance of ReRange
--> a.py:10:5
|
10 | rr : ReRange
| ^^^^^^^^^^^^ The issue is that This was done in #1808. I think we should relax this requirement. The reason we did (I think) is that it's relatively easy to enforce the struct to be initialized. But as we can see now, there is a use case when this is not a good idea. @Shaikh-Ubaid if you have time to have a look at this, that would be great. |
$ cat examples/expr2.py
from lpython import dataclass, i32
@dataclass
class A:
n: i32
def main0():
a: A
a.n = 5
print(a)
main0()
$ python examples/expr2.py
Traceback (most recent call last):
File "/Users/ubaid/Desktop/OpenSource/lpython/examples/expr2.py", line 12, in <module>
main0()
File "/Users/ubaid/Desktop/OpenSource/lpython/examples/expr2.py", line 9, in main0
a.n = 5
UnboundLocalError: local variable 'a' referenced before assignment
$ lpython examples/expr2.py
5 It seems CPython does not define a variable unless it is assigned. Since everything that compiles/runs with LPython should run with CPython, to tackle cases as above, we made it mandatory to initialize the variable if is a not a Simple Type. We need to see for a possible Robust fix/approach here. |
If anyone have any ideas, please feel free to share. For the moment, I am assigning this to me. |
I would fix this issue as follows. This should not be allowed:
Rather, either this:
or this must be required:
The PR #1808 enforces the third option. We should also allow the second option, but not the first. The second option should also allow:
Note that for loop over a list of structs is not supported yet, but eventually it will be supported. |
I'll give another use case for This is better: def lexer_test() -> None: # lexer : InOut[LasrLexer]):
# Issue #1981
print('LEXER TEST')
# re-use these variables multiple times
lexer : LasrLexer
t : str
# first test
lexer = LasrLexer(StringIO(' foo bar '))
__post_init__(lexer.fd)
eat_white(lexer)
t = peek_debug(lexer)
# Issue 1971 print({"t": t})
assert t == 'f', "t == 'f'"
# second test
lexer = LasrLexer(StringIO('(Integer 4 [])'))
__post_init__(lexer.fd)
t = get_non_white((lexer))
assert t == '(', "t = '('" because we can freely re-order the tests, than this: def lexer_test() -> None: # lexer : InOut[LasrLexer]):
# Issue #1981
print('LEXER TEST')
# first test
lexer : LasrLexer = LasrLexer(StringIO(' foo bar '))
__post_init__(lexer.fd)
eat_white(lexer)
t : str = peek_debug(lexer)
# Issue 1971 print({"t": t})
assert t == 'f', "t == 'f'"
# second test
lexer = LasrLexer(StringIO('(Integer 4 [])'))
__post_init__(lexer.fd)
t = get_non_white((lexer))
assert t == '(', "t = '('" The latter is what we must do now, due to LPython limitations. If we reorder the tests, we must edit them to ensure that the first one has the initialization. |
Not sure whether this is intentional.
repro: https://github.com/rebcabin/lpython/tree/brian-lasr/lasr/LP-pycharm/Issue1990
CPython:
LPython:
The text was updated successfully, but these errors were encountered: