New variable bindings are created for existing local variables
Currently, StaticLint handles any assignment as a new declaration. If we assign a different value to an existing variable, it is treated as a new variable with the same name, and any new references can only be traced back to this second assignment.
As an example, consider the following code excerpt:
function foo()
a = 0
for x in [1, 2, 3]
a = x
end
a
end
If we run this code and call the function, we can see that it returns the value 3. This is expected, as it is described in Julia's documentation. When we assign to an existing local variable, as is the case here, the existing variable is assigned. As a result, all 3 references of the variable a should have the same Binding. As we will see, this is not currently the case with StaticLint.
I saved this function to a file named test.jl, loaded it, and called scopepass on it, as follows:
using StaticLint, CSTParser
function loadfile(path::AbstractString)
server = StaticLint.FileServer();
source = read(path, String)
cst = CSTParser.parse(source, true)
file = StaticLint.File(path, source, cst, nothing, server)
StaticLint.setroot(file, file)
StaticLint.setfile(server, path, file)
StaticLint.scopepass(file)
return file.cst
end
cst = loadfile("test.jl")
println(cst)
This outputs:
1:96 FileH( new scope)
1:81 FunctionDef( Binding(foo:: (2 refs)) new scope)
1:9 FUNCTION
10:19 Call( )
10:12 foo *
13:13 (
14:19 )
20:76 Block( )
20:29 BinaryOpCall( )
20:21 aBinding(a:: (2 refs)) *
22:23 OP: EQ
24:29 INTEGER: 0
30:74 For( new scope)
30:33 FOR
34:56 BinaryOpCall( )
34:35 xBinding(x(2 refs)) *
36:38 OP: IN
39:56 Vect( )
39:39 [
40:40 INTEGER: 1
41:42 ,
43:43 INTEGER: 2
44:45 ,
46:46 INTEGER: 3
47:56 ]
57:66 Block( )
57:66 BinaryOpCall( )
57:58 aBinding(a(1 refs)) *
59:60 OP: EQ
61:66 x *
67:74 END
75:76 a *
77:81 END
82:96 Call( )
82:88 println *
89:89 (
90:94 Call( )
90:92 foo *
93:93 (
94:94 )
95:96 )
We can see that the a variable within the for loop creates a new bindings, which should not be the case. It should be a reference to the original variable, and added to the Binding's refs. This seems like a bug, unless I misunderstood something (which is not impossible, given that my usage of this package is based on experimentation).