quick_lambda.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. from macropy.core.macros import *
  2. from macropy.core.quotes import macros, q, ast, u
  3. from macropy.core.hquotes import macros, hq, ast, u, name
  4. from macropy.core.cleanup import ast_ctx_fixer
  5. macros = Macros()
  6. def _():
  7. """Placeholder for a function argument in the `f` macro."""
  8. @macros.expr
  9. def f(tree, gen_sym, **kw):
  10. """Macro to concisely create function literals; any `_`s within the
  11. wrapped expression becomes an argument to the generated function."""
  12. @Walker
  13. def underscore_search(tree, collect, **kw):
  14. if isinstance(tree, Name) and tree.id == "_":
  15. name = gen_sym("_")
  16. tree.id = name
  17. collect(name)
  18. return tree
  19. tree, used_names = underscore_search.recurse_collect(tree)
  20. new_tree = q[lambda: ast[tree]]
  21. new_tree.args.args = [Name(id = x) for x in used_names]
  22. return new_tree
  23. @macros.expr
  24. def lazy(tree, **kw):
  25. """Macro to wrap an expression in a lazy memoizing thunk. This can be
  26. called via `thing()` to extract the value. The wrapped expression is
  27. only evaluated the first time the thunk is called and the result cached
  28. for all subsequent evaluations."""
  29. return hq[Lazy(lambda: ast[tree])]
  30. def get_interned(store, index, thunk):
  31. if store[index] is None:
  32. store[index] = [thunk()]
  33. return store[index][0]
  34. @register(injected_vars)
  35. def interned_count(**kw):
  36. return [0]
  37. @register(injected_vars)
  38. def interned_name(gen_sym, **kw):
  39. return gen_sym()
  40. @register(post_processing)
  41. def interned_processing(tree, gen_sym, interned_count, interned_name, **kw):
  42. if interned_count[0] != 0:
  43. with q as code:
  44. name[interned_name] = [None for x in range(u[interned_count[0]])]
  45. code = ast_ctx_fixer.recurse(code)
  46. code = map(fix_missing_locations, code)
  47. tree.body = code + tree.body
  48. return tree
  49. @macros.expr
  50. def interned(tree, interned_name, interned_count, **kw):
  51. """Macro to intern the wrapped expression on a per-module basis"""
  52. interned_count[0] += 1
  53. return hq[get_interned(name[interned_name], interned_count[0] - 1, lambda: ast[tree])]