Skip to content

Bind with ... as targets to __enter__() return values#788

Open
BI71317 wants to merge 1 commit intoexaloop:developfrom
BI71317:pr-with-syntax
Open

Bind with ... as targets to __enter__() return values#788
BI71317 wants to merge 1 commit intoexaloop:developfrom
BI71317:pr-with-syntax

Conversation

@BI71317
Copy link
Copy Markdown
Contributor

@BI71317 BI71317 commented Apr 3, 2026

Limitation of this PR

This PR addresses only the first item of #787 : binding the result of __enter__() to the as target.

Current state in pseudo code

The below code interpreted differently in each codon and python:

with Manager() as pair:
	body

In Codon

Lowering current with syntax in Codon behaves conceptually like this:

# assign Class Instance
pair = Manager()
# Only calls _enter_ method
pair.__enter__()
try:
    ...
finally:
    pair.__exit__()

In Codon, pair refers to the Manager Class instance in Codon, and the return value of __enter__() is discarded.

In Python

In a While, with syntax in Python behaves like below pseudo code:

# first  assign temporal Class instance
temp = Manager()
# assigns class methods
enter = temp.__enter__
exit = temp.__exit__
# Binding “pair” identifier with return value of enter method.
pair = enter()

try:
    ...
except:
    ...
finally:
    pair.__exit__()

https://docs.python.org/3/reference/compound_stmts.html#the-with-statement
In Python, pair refers to the return value of __enter__() .

What this PR fixes

Conceptually, lowering changes to:

_mgr = Manager()
var = _mgr.__enter__()
try:
    body
finally:
    _mgr.__exit__()

@BI71317 BI71317 requested a review from inumanag as a code owner April 3, 2026 02:52
@cla-bot cla-bot Bot added the cla-signed label Apr 3, 2026
@BI71317
Copy link
Copy Markdown
Contributor Author

BI71317 commented Apr 3, 2026

And, yeah. It conflicts every other test cases with current with .. as .. syntaxes.

in codon\test\parser\typecheck\test_function.codon

#%% with,barebones
class Foo:
    i: int
    def __enter__(self: Foo):
        print '> foo! ' + str(self.i)
    def __exit__(self: Foo):
        print '< foo! ' + str(self.i)
    def foo(self: Foo):
        print 'woof'
class Bar:
    s: str
    def __enter__(self: Bar):
        print '> bar! ' + self.s
    def __exit__(self: Bar):
        print '< bar! ' + self.s
    def bar(self: Bar):
        print 'meow'
with Foo(0) as f:
#: > foo! 0
    f.foo()  #: woof
#: < foo! 0
with Foo(1) as f, Bar('s') as b:
#: > foo! 1
#: > bar! s
    f.foo()  #: woof
    b.bar()  #: meow
#: < bar! s
#: < foo! 1
with Foo(2), Bar('t') as q:
#: > foo! 2
#: > bar! t
    print 'eeh'  #: eeh
    q.bar()  #: meow
#: < bar! t
#: < foo! 2
[  FAILED  ] 9 tests, listed below:
[  FAILED  ] TypeTests/SeqTest.Run/parser_typecheck_test_function_codon_debug_198_with, where GetParam() = ("parser/typecheck/test_function.codon", true, "198_with", "#%% with,barebones\nclass Foo:\n    i: int\n    def __enter__(self: Foo):\n        print '> foo! ' + str(self.i)\n    def __exit__(self: Foo):\n        print '< foo! ' + str(self.i)\n    def foo(self: Foo):\n        print 'woof'\nclass Bar:\n    s: str\n    def __enter__(self: Bar):\n        print '> bar! ' + self.s\n    def __exit__(self: Bar):\n        print '< bar! ' + self.s\n    def bar(self: Bar):\n        print 'meow'\nwith Foo(0) as f:\n#: > foo! 0\n    f.foo()  #: woof\n#: < foo! 0\nwith Foo(1) as f, Bar('s') as b:\n#: > foo! 1\n#: > bar! s\n    f.foo()  #: woof\n    b.bar()  #: meow\n#: < bar! s\n#: < foo! 1\nwith Foo(2), Bar('t') as q:\n#: > foo! 2\n#: > bar! t\n    print 'eeh'  #: eeh\n    q.bar()  #: meow\n#: < bar! t\n#: < foo! 2\n\n\n", 161, true, false, true)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant