xsrule.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. '''This file is part of AToMPM - A Tool for Multi-Paradigm Modelling
  2. Copyright 2011 by the AToMPM team and licensed under the LGPL
  3. See COPYING.lesser and README.md in the root of this project for full details'''
  4. from ..util.infinity import INFINITY
  5. from .srule import SRule
  6. from ..tcore.rollbacker import Rollbacker
  7. from ..tcore.resolver import Resolver
  8. class XSRule(SRule):
  9. '''
  10. Applies the transformation as long as matches can be found with roll-back capability.
  11. '''
  12. def __init__(self, LHS, RHS, max_iterations=INFINITY):
  13. '''
  14. Applies the transformation on all matches found with roll-back capability.
  15. @param LHS: The pre-condition pattern (LHS + NACs).
  16. @param RHS: The post-condition pattern (RHS).
  17. @param max_iterations: The maximum number of times to match.
  18. '''
  19. super(XSRule, self).__init__(LHS, RHS, max_iterations)
  20. # max_iterations=1 because no all matches have been exhausted after first application
  21. self.B = Rollbacker(condition=LHS, max_iterations=1)
  22. def packet_in(self, packet):
  23. self.exception = None
  24. self.is_success = False
  25. # Checkpoint the original packet
  26. self.B.packet_in(packet)
  27. if not self.B.is_success:
  28. self.exception = self.B.exception
  29. return packet
  30. # Match
  31. packet = self.M.packet_in(packet)
  32. if not self.M.is_success:
  33. packet = self.B.restore()
  34. if self.M.exception:
  35. self.exception = self.M.exception
  36. elif self.B.exception:
  37. self.exception = self.B.exception
  38. return packet
  39. # Choose the first match
  40. packet = self.I.packet_in(packet)
  41. if not self.I.is_success:
  42. packet = self.B.restore()
  43. if self.I.exception:
  44. self.exception = self.I.exception
  45. elif self.B.exception:
  46. self.exception = self.B.exception
  47. return packet
  48. while True:
  49. # Rewrite
  50. packet = self.W.packet_in(packet)
  51. if not self.W.is_success:
  52. packet = self.B.restore()
  53. if self.W.exception:
  54. self.exception = self.W.exception
  55. elif self.B.exception:
  56. self.exception = self.B.exception
  57. return packet
  58. # Rule has been applied once, so it's a success anyway
  59. self.is_success = True
  60. if self.I.iterations == self.I.max_iterations:
  61. return packet
  62. # Re-Match
  63. packet = self.M.packet_in(packet)
  64. if not self.M.is_success:
  65. self.exception = self.M.exception
  66. return packet
  67. # Choose another match
  68. packet = self.I.next_in(packet)
  69. # No more iterations are left
  70. if not self.I.is_success:
  71. if self.I.exception:
  72. packet = self.B.restore()
  73. if self.B.exception:
  74. self.exception = self.B.exception
  75. self.exception = self.I.exception
  76. self.is_success = False
  77. return packet
  78. def next_in(self, packet):
  79. # Only one roll-back
  80. self.exception = None
  81. self.is_success = False
  82. packet = self.B.next_in(packet)
  83. if not self.B.is_success:
  84. self.exception = self.B.exception
  85. return packet
  86. class XSRule_r(XSRule):
  87. '''
  88. Applies the transformation as long as matches can be found with roll-back capability.
  89. '''
  90. def __init__(self, LHS, RHS, max_iterations=INFINITY, external_matches_only=False, custom_resolution=lambda packet: False):
  91. '''
  92. Applies the transformation as long as matches can be found with roll-back capability.
  93. @param LHS: The pre-condition pattern (LHS + NACs).
  94. @param RHS: The post-condition pattern (RHS).
  95. @param max_iterations: The maximum number of times to apply the rule.
  96. @param external_matches_only: Resolve conflicts ignoring the matches found in this FRule.
  97. @param custom_resolution: Override the default resolution function.
  98. '''
  99. super(XSRule_r, self).__init__(LHS, RHS, max_iterations)
  100. self.R = Resolver(external_matches_only=external_matches_only,
  101. custom_resolution=custom_resolution)
  102. def packet_in(self, packet):
  103. self.exception = None
  104. self.is_success = False
  105. # Checkpoint the original packet
  106. self.B.packet_in(packet)
  107. if not self.B.is_success:
  108. self.exception = self.B.exception
  109. return packet
  110. # Match
  111. packet = self.M.packet_in(packet)
  112. if not self.M.is_success:
  113. packet = self.B.restore()
  114. if self.M.exception:
  115. self.exception = self.M.exception
  116. elif self.B.exception:
  117. self.exception = self.B.exception
  118. return packet
  119. # Choose the first match
  120. packet = self.I.packet_in(packet)
  121. if not self.I.is_success:
  122. packet = self.B.restore()
  123. if self.I.exception:
  124. self.exception = self.I.exception
  125. elif self.B.exception:
  126. self.exception = self.B.exception
  127. return packet
  128. while True:
  129. # Rewrite
  130. packet = self.W.packet_in(packet)
  131. if not self.W.is_success:
  132. packet = self.B.restore()
  133. if self.W.exception:
  134. self.exception = self.W.exception
  135. elif self.B.exception:
  136. self.exception = self.B.exception
  137. return packet
  138. # Resolve any conflicts if necessary
  139. packet = self.R.packet_in(packet)
  140. if not self.R.is_success:
  141. self.exception = self.R.exception
  142. return packet
  143. # Rule has been applied once, so it's a success anyway
  144. self.is_success = True
  145. if self.I.iterations == self.I.max_iterations:
  146. return packet
  147. # Re-Match
  148. packet = self.M.packet_in(packet)
  149. if not self.M.is_success:
  150. self.exception = self.M.exception
  151. return packet
  152. # Choose another match
  153. packet = self.I.next_in(packet)
  154. # No more iterations are left
  155. if not self.I.is_success:
  156. if self.I.exception:
  157. packet = self.B.restore()
  158. if self.B.exception:
  159. self.exception = self.B.exception
  160. self.exception = self.I.exception
  161. self.is_success = False
  162. return packet