2 require 'metalua.walk.scope'
5 -- binders :: ast => name => occurences
6 -- unbound :: name => occurences
7 -- scope :: name => ast
9 local binders, unbound, cfg, scope = { }, { }, { scope={ } }, scope:new()
11 -- * id: identifier entering in scope
12 -- * ast: statement or expr carrying this id, on of:
13 -- Local, Localrec, Forin, Fornum, Function.
14 function cfg.binder (id, ast)
15 if id.tag ~= 'Id' then return end
17 -- Reference in scope, so that the binding statement can be retrieved:
18 scope.current[id_name] = ast
19 -- Init the occurences list for this identifier:
20 if binders[ast] then binders[ast][id_name] = { }
21 else binders[ast] = { [id_name] = { } } end
24 -- identifier occurence, not as a binder: reference this occurence
27 -- ast which binds this id, might be nil:
28 local binder_ast = scope.current [id_name]
29 -- dict id_name => occurences, might be the list of unbound occurences:
30 local occur_dict = binder_ast and binders[binder_ast] or unbound
31 -- add an occurence of `id' in the occurences list:
32 local occurences = occur_dict [id_name]
33 if occurences then table.insert (occurences, id)
34 else occur_dict [id_name] = { id } end
37 function cfg.scope.down() scope:push() end
38 function cfg.scope.up() scope:pop() end
41 return binders, unbound