possibilities.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. # Each rule will append its hint message to the following dictionary. The
  2. # function pointer to the apply function of the rule is used as key. The
  3. # corresponding value is a string, which will be used to produce the hint
  4. # message. The string will be processed using string.format().
  5. MESSAGES = {}
  6. class Possibility(object):
  7. def __init__(self, root, handler, args=()):
  8. self.root = root
  9. self.handler = handler
  10. self.args = args
  11. def __str__(self):
  12. if self.handler in MESSAGES:
  13. return MESSAGES[self.handler].format(self.root, *self.args)
  14. return self.__repr__()
  15. def __repr__(self):
  16. return '<Possibility root="%s" handler=%s args=%s>' \
  17. % (self.root, self.handler.func_name, self.args)
  18. def __eq__(self, other):
  19. return self.handler == other.handler \
  20. and hash(self.root) == hash(other.root) \
  21. and self.args == other.args
  22. def filter_duplicates(possibilities):
  23. """
  24. Filter duplicated possibilities. Duplicated possibilities occur in n-ary
  25. nodes, the root-level node and a lower-level node will both recognize a
  26. rewrite possibility within their scope, whereas only the root-level one
  27. matters.
  28. Example: 1 + 2 + 3
  29. The addition of 1 and 2 is recognized by n-ary additions "1 + 2" and
  30. "1 + 2 + 3". The "1 + 2" addition should be removed by this function.
  31. """
  32. features = []
  33. unique = []
  34. for p in reversed(possibilities):
  35. feature = (p.handler, p.args)
  36. if feature not in features:
  37. features.append(feature)
  38. unique.insert(0, p)
  39. return unique
  40. def pick_suggestion(possibilities):
  41. if not possibilities:
  42. return
  43. # TODO: pick the best suggestion.
  44. suggestion = 0
  45. return possibilities[suggestion]
  46. def apply_suggestion(root, subtree_map, suggestion):
  47. # TODO: clone the root node before modifying. After deep copying the root
  48. # node, the subtree_map cannot be used since the hash() of each node in the
  49. # deep copied root node has changed.
  50. #root_clone = root.clone()
  51. subtree = suggestion.handler(suggestion.root, suggestion.args)
  52. if suggestion.root in subtree_map:
  53. parent_node = subtree_map[suggestion.root]
  54. else:
  55. parent_node = None
  56. # There is either a parent node or the subtree is the root node.
  57. # FIXME: FAIL: test_diagnostic_test_application in tests/test_b1_ch08.py
  58. #try:
  59. # assert bool(parent_node) != (subtree == root)
  60. #except:
  61. # print 'parent_node: %s' % (str(parent_node))
  62. # print 'subtree: %s == %s' % (str(subtree), str(root))
  63. # raise
  64. if parent_node:
  65. parent_node.substitute(suggestion.root, subtree)
  66. return root
  67. return subtree