Variables in nested closures #864

Closed
emilwestergren opened this Issue Feb 17, 2015 · 4 comments

Projects

None yet

3 participants

@emilwestergren

Should it be possible to create a closure inside another closure? Because it is in that case not possible to use variables created in the parent closure in the child closure.

Example code:

func1 := func {
    a := 1
    b := 2
    func2 := func { println((a + b) toString()) }
    func2()
}
func1()

fails with:

NestedClosureTest.ooc: In function ‘test_sdk_NestedClosureTest_load’:
NestedClosureTest.ooc:3:13: error: ‘a’ undeclared (first use in this function)
  a := 1
             ^
NestedClosureTest.ooc:3:13: note: each undeclared identifier is reported only once for each function it appears in
NestedClosureTest.ooc:4:13: error: ‘b’ undeclared (first use in this function)
  b := 2
             ^
NestedClosureTest.ooc: In function ‘test_sdk_NestedClosureTest____test_sdk_NestedClosureTest_test_sdk_NestedClosureTest_closure4’:
NestedClosureTest.ooc:3:23: error: ‘a’ redeclared as different kind of symbol
  a := 1
                       ^
NestedClosureTest.ooc:8:117: note: previous definition of ‘a’ was here
 func1()
                                                                                                                     ^
NestedClosureTest.ooc:4:23: error: ‘b’ redeclared as different kind of symbol
  b := 2
                       ^
NestedClosureTest.ooc:8:138: note: previous definition of ‘b’ was here
 func1()
@zhaihj
Contributor
zhaihj commented Feb 17, 2015

Things messed up when variable appears.
line no.104,105 cause this problem. Here we are generating unnecessary context __vvv_ctx5.

101         __vvv_ctx5 = lang_Memory__gc_malloc(((lang_types__Class*)__vvv_vvv_closure4_ctx_class())->size);
102         #line 1 "/home/housezet/.ooc_libs/mcs/test/rock/vvv.ooc"
103         (*(__vvv_ctx5)) = (__vvv_vvv_closure4_ctx) {
104             a,
105             b
106         };
107         __vvv_closure6 = (lang_types__Closure) {
108             vvv____vvv_vvv_closure4_thunk,
109             __vvv_ctx5
110         };
@zhaihj
Contributor
zhaihj commented Feb 17, 2015

It seems to be a bug in VariableDecl -> captureInUpstreamClosures -> intermediateScopeIndex
W should also check if var is defined in parent closure.

@zhaihj zhaihj added a commit to zhaihj/rock that referenced this issue Feb 17, 2015
@zhaihj zhaihj fix #864 a19318b
@zhaihj
Contributor
zhaihj commented Feb 20, 2015

A related problem(UNRESOLVED):

main: func{
    ret := 1
    1 times(|| 2 times(|| ret += 1))
    ret toString() println()
}

Expect: 3
Got: 1

because rock generate &(&ret) in nested closure...

This was referenced Mar 5, 2015
@fasterthanlime
Collaborator

My example (for the original issue, not #882)

func1 := func {
    a := 1
    b := 2
    func2 := func {
        "#{a + b}" println()
    }
    func2()
}
func1()

Note that if you change func1 := to func1: it doesn't happen. Looks like isDefined doesn't do the right thing..

@fasterthanlime fasterthanlime modified the milestone: 0.9.10 Jul 10, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment