This repo contains code to mirror other repos. It also contains the code that is getting mirrored.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

192 lines
4.8 KiB

  1. from inspect import isclass, getmembers, getmro
  2. from functools import wraps
  3. from .utils import smart_decorator
  4. from .tree import Tree
  5. class Discard(Exception):
  6. pass
  7. class Base:
  8. def _call_userfunc(self, tree):
  9. return getattr(self, tree.data, self.__default__)(tree)
  10. def __default__(self, tree):
  11. "Default operation on tree (for override)"
  12. return tree
  13. @classmethod
  14. def _apply_decorator(cls, decorator):
  15. mro = getmro(cls)
  16. assert mro[0] is cls
  17. libmembers = {name for _cls in mro[1:] for name, _ in getmembers(_cls)}
  18. for name, value in getmembers(cls):
  19. if name.startswith('_') or name in libmembers:
  20. continue
  21. setattr(cls, name, decorator(value))
  22. return cls
  23. class SimpleBase(Base):
  24. def _call_userfunc(self, tree):
  25. # Assumes tree is already transformed
  26. try:
  27. f = getattr(self, tree.data)
  28. except AttributeError:
  29. return self.__default__(tree)
  30. else:
  31. return f(tree.children)
  32. class Transformer(Base):
  33. def _transform_children(self, children):
  34. for c in children:
  35. try:
  36. yield self._transform_tree(c) if isinstance(c, Tree) else c
  37. except Discard:
  38. pass
  39. def _transform_tree(self, tree):
  40. tree = Tree(tree.data, list(self._transform_children(tree.children)))
  41. return self._call_userfunc(tree)
  42. def transform(self, tree):
  43. return self._transform_tree(tree)
  44. def __mul__(self, other):
  45. return TransformerChain(self, other)
  46. class TransformerChain(object):
  47. def __init__(self, *transformers):
  48. self.transformers = transformers
  49. def transform(self, tree):
  50. for t in self.transformers:
  51. tree = t.transform(tree)
  52. return tree
  53. def __mul__(self, other):
  54. return TransformerChain(*self.transformers + (other,))
  55. class Transformer_InPlace(Transformer):
  56. def _transform_tree(self, tree): # Cancel recursion
  57. return self._call_userfunc(tree)
  58. def transform(self, tree):
  59. for subtree in tree.iter_subtrees():
  60. subtree.children = list(self._transform_children(subtree.children))
  61. return self._transform_tree(tree)
  62. class Transformer_InPlaceRecursive(Transformer):
  63. def _transform_tree(self, tree):
  64. tree.children = list(self._transform_children(tree.children))
  65. return self._call_userfunc(tree)
  66. class Visitor(Base):
  67. "Bottom-up visitor"
  68. def visit(self, tree):
  69. for subtree in tree.iter_subtrees():
  70. self._call_userfunc(subtree)
  71. return tree
  72. class Visitor_Recursive(Base):
  73. def visit(self, tree):
  74. for child in tree.children:
  75. if isinstance(child, Tree):
  76. self.visit(child)
  77. f = getattr(self, tree.data, self.__default__)
  78. f(tree)
  79. return tree
  80. def visit_children_decor(func):
  81. @wraps(func)
  82. def inner(cls, tree):
  83. values = cls.visit_children(tree)
  84. return func(cls, values)
  85. return inner
  86. class Interpreter(object):
  87. "Top-down visitor"
  88. def visit(self, tree):
  89. return getattr(self, tree.data)(tree)
  90. def visit_children(self, tree):
  91. return [self.visit(child) if isinstance(child, Tree) else child
  92. for child in tree.children]
  93. def __getattr__(self, name):
  94. return self.__default__
  95. def __default__(self, tree):
  96. return self.visit_children(tree)
  97. def _apply_decorator(obj, decorator):
  98. try:
  99. _apply = obj._apply_decorator
  100. except AttributeError:
  101. return decorator(obj)
  102. else:
  103. return _apply(decorator)
  104. def _children_args__func(func):
  105. if getattr(func, '_children_args_decorated', False):
  106. return func
  107. @wraps(func)
  108. def create_decorator(_f, with_self):
  109. if with_self:
  110. def f(self, tree):
  111. return _f(self, tree.children)
  112. else:
  113. def f(args):
  114. return _f(tree.children)
  115. f._children_args_decorated = True
  116. return f
  117. return smart_decorator(func, create_decorator)
  118. def children_args(obj):
  119. return _apply_decorator(obj, _children_args__func)
  120. def _children_args_inline__func(func):
  121. if getattr(func, '_children_args_decorated', False):
  122. return func
  123. @wraps(func)
  124. def create_decorator(_f, with_self):
  125. if with_self:
  126. def f(self, tree):
  127. return _f(self, *tree.children)
  128. else:
  129. def f(self, tree):
  130. print ('##', _f, tree)
  131. return _f(*tree.children)
  132. f._children_args_decorated = True
  133. return f
  134. return smart_decorator(func, create_decorator)
  135. def children_args_inline(obj):
  136. return _apply_decorator(obj, _children_args_inline__func)