1234567891011121314151617181920212223242526272829303132333435363738394041 |
- """Logic related to generated a stream of unique symbols for macros to use.
- Exposes this functionality as the `gen_sym` function.
- """
- from macropy.core.macros import *
- @register(injected_vars)
- def gen_sym(tree, **kw):
- """Create a generator that creates symbols which are not used in the given
- `tree`. This means they will be hygienic, i.e. it guarantees that they will
- not cause accidental shadowing, as long as the scope of the new symbol is
- limited to `tree` e.g. by a lambda expression or a function body"""
- @Walker
- def name_finder(tree, collect, **kw):
- if type(tree) is Name:
- collect(tree.id)
- if type(tree) is Import:
- names = [x.asname or x.name for x in tree.names]
- map(collect, names)
- if type(tree) is ImportFrom:
- names = [x.asname or x.name for x in tree.names]
- map(collect, names)
- if type(tree) in (FunctionDef, ClassDef):
- collect(tree.name)
- found_names = set(name_finder.collect(tree))
- def name_for(name="sym"):
- if name not in found_names:
- found_names.add(name)
- return name
- offset = 1
- while name + str(offset) in found_names:
- offset += 1
- found_names.add(name + str(offset))
- return name + str(offset)
- return name_for
|