gen_sym.py 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. """Logic related to generated a stream of unique symbols for macros to use.
  2. Exposes this functionality as the `gen_sym` function.
  3. """
  4. from macropy.core.macros import *
  5. @register(injected_vars)
  6. def gen_sym(tree, **kw):
  7. """Create a generator that creates symbols which are not used in the given
  8. `tree`. This means they will be hygienic, i.e. it guarantees that they will
  9. not cause accidental shadowing, as long as the scope of the new symbol is
  10. limited to `tree` e.g. by a lambda expression or a function body"""
  11. @Walker
  12. def name_finder(tree, collect, **kw):
  13. if type(tree) is Name:
  14. collect(tree.id)
  15. if type(tree) is Import:
  16. names = [x.asname or x.name for x in tree.names]
  17. map(collect, names)
  18. if type(tree) is ImportFrom:
  19. names = [x.asname or x.name for x in tree.names]
  20. map(collect, names)
  21. if type(tree) in (FunctionDef, ClassDef):
  22. collect(tree.name)
  23. found_names = set(name_finder.collect(tree))
  24. def name_for(name="sym"):
  25. if name not in found_names:
  26. found_names.add(name)
  27. return name
  28. offset = 1
  29. while name + str(offset) in found_names:
  30. offset += 1
  31. found_names.add(name + str(offset))
  32. return name + str(offset)
  33. return name_for