@@ -753,9 +753,156 @@ local function createLocal(obj, attrs)
753753 return obj
754754end
755755
756+ local function getLocal (name , pos )
757+ for i = # Chunk , 1 , - 1 do
758+ local chunk = Chunk [i ]
759+ local locals = chunk .locals
760+ if locals then
761+ local res
762+ for n = 1 , # locals do
763+ local loc = locals [n ]
764+ if loc .effect > pos then
765+ break
766+ end
767+ if loc [1 ] == name then
768+ if not res or res .effect < loc .effect then
769+ res = loc
770+ end
771+ end
772+ end
773+ if res then
774+ return res
775+ end
776+ end
777+ end
778+ end
779+
780+ local function getVariable (name , pos )
781+ for i = # Chunk , 1 , - 1 do
782+ local chunk = Chunk [i ]
783+ local resLocal
784+ local resGlobal
785+
786+ -- Find most recent local in this chunk
787+ local locals = chunk .locals
788+ if locals then
789+ for n = 1 , # locals do
790+ local loc = locals [n ]
791+ if loc .effect > pos then
792+ break
793+ end
794+ if loc [1 ] == name then
795+ if not resLocal or resLocal .effect < loc .effect then
796+ resLocal = loc
797+ end
798+ end
799+ end
800+ end
801+
802+ -- Find global in this chunk (globals don't have effect time, just find the last one)
803+ local globals = chunk .globals
804+ if globals then
805+ for n = # globals , 1 , - 1 do
806+ local glob = globals [n ]
807+ if glob [1 ] == name then
808+ resGlobal = glob
809+ break
810+ end
811+ end
812+ end
813+
814+ -- Return the one declared later (compare by start position)
815+ if resLocal and resGlobal then
816+ if resLocal .start > resGlobal .start then
817+ return resLocal
818+ else
819+ return resGlobal
820+ end
821+ end
822+ if resLocal then
823+ return resLocal
824+ end
825+ if resGlobal then
826+ return resGlobal
827+ end
828+ end
829+
830+ -- If not found, look for global *
831+ for i = # Chunk , 1 , - 1 do
832+ local chunk = Chunk [i ]
833+ local globals = chunk .globals
834+ if globals then
835+ for n = # globals , 1 , - 1 do
836+ local glob = globals [n ]
837+ if glob [1 ] == ' *' then
838+ return glob
839+ end
840+ end
841+ end
842+ end
843+
844+ return nil
845+ end
846+
847+ local function linkGlobalToEnv (node , var )
848+ -- Lua 5.5: Check VARIABLE_NOT_DECLARED
849+ if State .version == ' Lua 5.5' and not var then
850+ -- Check if there's any global declaration in scope
851+ local hasAnyGlobal = false
852+ for i = # Chunk , 1 , - 1 do
853+ local chunk = Chunk [i ]
854+ if chunk .globals and # chunk .globals > 0 then
855+ hasAnyGlobal = true
856+ break
857+ end
858+ end
859+
860+ if hasAnyGlobal then
861+ pushError {
862+ type = ' VARIABLE_NOT_DECLARED' ,
863+ start = node .start ,
864+ finish = node .finish ,
865+ }
866+ end
867+ end
868+
869+ -- Lua 5.5: Use getVariable to find _ENV, check if it's global
870+ local env
871+ if State .version == ' Lua 5.5' then
872+ env = getVariable (State .ENVMode , node .start )
873+ if env and env .type == ' global' then
874+ pushError {
875+ type = ' RUNTIME_ERROR' ,
876+ start = node .start ,
877+ finish = node .finish ,
878+ info = {
879+ message = ' _ENV is global when accessing variable'
880+ }
881+ }
882+ end
883+ if env and env .type == ' local' then
884+ node .node = env
885+ if not env .ref then
886+ env .ref = {}
887+ end
888+ env .ref [# env .ref + 1 ] = node
889+ end
890+ else
891+ env = getLocal (State .ENVMode , node .start )
892+ if env then
893+ node .node = env
894+ if not env .ref then
895+ env .ref = {}
896+ end
897+ env .ref [# env .ref + 1 ] = node
898+ end
899+ end
900+ end
901+
756902--- @param obj table
757- local function createGlobal (obj , attrs )
758- obj .type = ' globaldeclare'
903+ local function createGlobalDeclare (obj , attrs )
904+ obj .type = ' setglobal'
905+ obj .declare = true
759906
760907 if attrs then
761908 obj .attrs = attrs
@@ -771,6 +918,9 @@ local function createGlobal(obj, attrs)
771918 end
772919 globals [# globals + 1 ] = obj
773920 end
921+
922+ linkGlobalToEnv (obj , obj )
923+
774924 return obj
775925end
776926
@@ -2111,97 +2261,6 @@ local function parseParen()
21112261 return paren
21122262end
21132263
2114- local function getLocal (name , pos )
2115- for i = # Chunk , 1 , - 1 do
2116- local chunk = Chunk [i ]
2117- local locals = chunk .locals
2118- if locals then
2119- local res
2120- for n = 1 , # locals do
2121- local loc = locals [n ]
2122- if loc .effect > pos then
2123- break
2124- end
2125- if loc [1 ] == name then
2126- if not res or res .effect < loc .effect then
2127- res = loc
2128- end
2129- end
2130- end
2131- if res then
2132- return res
2133- end
2134- end
2135- end
2136- end
2137-
2138- local function getVariable (name , pos )
2139- for i = # Chunk , 1 , - 1 do
2140- local chunk = Chunk [i ]
2141- local resLocal
2142- local resGlobal
2143-
2144- -- Find most recent local in this chunk
2145- local locals = chunk .locals
2146- if locals then
2147- for n = 1 , # locals do
2148- local loc = locals [n ]
2149- if loc .effect > pos then
2150- break
2151- end
2152- if loc [1 ] == name then
2153- if not resLocal or resLocal .effect < loc .effect then
2154- resLocal = loc
2155- end
2156- end
2157- end
2158- end
2159-
2160- -- Find global in this chunk (globals don't have effect time, just find the last one)
2161- local globals = chunk .globals
2162- if globals then
2163- for n = # globals , 1 , - 1 do
2164- local glob = globals [n ]
2165- if glob [1 ] == name then
2166- resGlobal = glob
2167- break
2168- end
2169- end
2170- end
2171-
2172- -- Return the one declared later (compare by start position)
2173- if resLocal and resGlobal then
2174- if resLocal .start > resGlobal .start then
2175- return resLocal
2176- else
2177- return resGlobal
2178- end
2179- end
2180- if resLocal then
2181- return resLocal
2182- end
2183- if resGlobal then
2184- return resGlobal
2185- end
2186- end
2187-
2188- -- If not found, look for global *
2189- for i = # Chunk , 1 , - 1 do
2190- local chunk = Chunk [i ]
2191- local globals = chunk .globals
2192- if globals then
2193- for n = # globals , 1 , - 1 do
2194- local glob = globals [n ]
2195- if glob [1 ] == ' *' then
2196- return glob
2197- end
2198- end
2199- end
2200- end
2201-
2202- return nil
2203- end
2204-
22052264local function resolveName (node )
22062265 if not node then
22072266 return nil
@@ -2221,58 +2280,7 @@ local function resolveName(node)
22212280 node .type = ' getglobal'
22222281 node .var = var
22232282
2224- -- Lua 5.5: Check VARIABLE_NOT_DECLARED
2225- if State .version == ' Lua 5.5' and not var then
2226- -- Check if there's any global declaration in scope
2227- local hasAnyGlobal = false
2228- for i = # Chunk , 1 , - 1 do
2229- local chunk = Chunk [i ]
2230- if chunk .globals and # chunk .globals > 0 then
2231- hasAnyGlobal = true
2232- break
2233- end
2234- end
2235-
2236- if hasAnyGlobal then
2237- pushError {
2238- type = ' VARIABLE_NOT_DECLARED' ,
2239- start = node .start ,
2240- finish = node .finish ,
2241- }
2242- end
2243- end
2244-
2245- -- Lua 5.5: Use getVariable to find _ENV, check if it's global
2246- local env
2247- if State .version == ' Lua 5.5' then
2248- env = getVariable (State .ENVMode , node .start )
2249- if env and env .type == ' global' then
2250- pushError {
2251- type = ' RUNTIME_ERROR' ,
2252- start = node .start ,
2253- finish = node .finish ,
2254- info = {
2255- message = ' _ENV is global when accessing variable'
2256- }
2257- }
2258- end
2259- if env and env .type == ' local' then
2260- node .node = env
2261- if not env .ref then
2262- env .ref = {}
2263- end
2264- env .ref [# env .ref + 1 ] = node
2265- end
2266- else
2267- env = getLocal (State .ENVMode , node .start )
2268- if env then
2269- node .node = env
2270- if not env .ref then
2271- env .ref = {}
2272- end
2273- env .ref [# env .ref + 1 ] = node
2274- end
2275- end
2283+ linkGlobalToEnv (node , var )
22762284 end
22772285 local name = node [1 ]
22782286 bindSpecial (node , name )
@@ -3344,7 +3352,7 @@ local function parseGlobal()
33443352 name .vstart = func .start
33453353 name .range = func .finish
33463354 func .parent = name
3347- createGlobal (name )
3355+ createGlobalDeclare (name )
33483356 pushActionIntoCurrentChunk (name )
33493357 return name
33503358 else
@@ -3378,7 +3386,7 @@ local function parseGlobal()
33783386 end
33793387 end
33803388 end
3381- createGlobal (action , attrs )
3389+ createGlobalDeclare (action , attrs )
33823390 Index = Index + 2
33833391 pushActionIntoCurrentChunk (action )
33843392 return action
@@ -3437,7 +3445,7 @@ local function parseGlobal()
34373445 glob .finish = attrsAfter [# attrsAfter ].finish
34383446 end
34393447
3440- createGlobal (glob , glob .attrs )
3448+ createGlobalDeclare (glob , glob .attrs )
34413449 pushActionIntoCurrentChunk (glob )
34423450 skipSpace ()
34433451
@@ -3485,7 +3493,7 @@ local function parseGlobal()
34853493 end
34863494 gN .finish = attrsNAfter [# attrsNAfter ].finish
34873495 end
3488- createGlobal (gN , gN .attrs )
3496+ createGlobalDeclare (gN , gN .attrs )
34893497 return gN
34903498 end
34913499 return nil
0 commit comments