Forum
Scope rules - Printable Version

+- Forum (https://www.boriel.com/forum)
+-- Forum: Compilers and Computer Languages (https://www.boriel.com/forum/forumdisplay.php?fid=12)
+--- Forum: ZX Basic Compiler (https://www.boriel.com/forum/forumdisplay.php?fid=11)
+---- Forum: Bug Reports (https://www.boriel.com/forum/forumdisplay.php?fid=15)
+---- Thread: Scope rules (/showthread.php?tid=2620)



Scope rules - Zoran - 04-03-2025

If we have got a routine and another subroutine nested inside the first, the programme behaves unpredictably.

I wanted to test if the variable declared in outer routine is accessible from the inner routine (I couldn't find it documented anywhere).


Please see these two simple examples which show quite different behaviour.

Both compiled with Zx Basic version 1.17.3, with these options:


Quote:--optimize 2 -f tzx --BASIC --autorun --explicit --strict

The first example:

Code:
#pragma explicit = true
#pragma strict = true

sub outerRoutine
    dim n as ubyte
   
    sub nestedRoutine()
        print "From inner sub, before: "; n
        n = 22
        print "From inner sub, after: "; n
    end sub
   
    n = 11
   
    print "From outer sub, before: "; n
    nestedRoutine()
    print "From outer sub, after: "; n
end sub

cls
outerRoutine()


The output:

Quote:From outer sub, before: 11
From inner sub, before: 11
From inner sub, after: 22
From outer sub, after: 22


So the first example shows that variable n, declared in outer routine is fully accessible from the nested routine.

In the second example, I only added a dummy variable declaration inside the nested routine:

Code:
#pragma explicit = true
#pragma strict = true

sub outerRoutine
    dim n as ubyte
   
    sub nestedRoutine()
        dim k as ubyte ' declare a dummy variable
        if k <> 0 then ' and access it
            print "";  ' do nothing meaningful
        end if
       
        print "From inner sub, before: "; n
        n = 22
        print "From inner sub, after: "; n
    end sub
   
    n = 11
   
    print "From outer sub, before: "; n
    nestedRoutine()
    print "From outer sub, after: "; n
end sub

cls
outerRoutine()

Quote:From outer sub, before: 11
From inner sub, before: 0
From inner sub, after: 22
From outer sub, after: 11

Totally different output!
The main problem is that, referring to variable n, something is accessed and even written to inside the nested subroutine, but it is clearly not the varible n declared above.

With explicit and strict options, if the outer routine scope is not accessible, the compiler has to give an error that variable n is not declared in routine innerRoutine.
The compiler gives no error, though. Then the programme behaviour is unpredictable and rather dangerous actually.


RE: Scope rules - boriel - 04-03-2025

Yes, the variable n is "Non local", that is, is not global, nor local, but in the closure of the outer scope.
This is not well supported yet, sorry, due to limitations of the Z80 registers (working on it yet...)


RE: Scope rules - Zoran - 04-04-2025

(04-03-2025, 10:09 PM)boriel Wrote: Yes, the variable n is "Non local", that is, is not global, nor local, but in the closure of the outer scope.
This is not well supported yet, sorry, due to limitations of the Z80 registers (working on it yet...)

This situation, when it works sometimes and sometimes not, is rather dangerous.
If it is not easy to implement, then just forbidding referencing of outer-scope local variables (compilation error), would be a good enough solution.
With "strict" option, one should expect safety. Not being able to reference outer-scope local variables is quite acceptable, can you implement this?