exp_scd.py 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. # Simple Class Diagram experiment
  2. from state.devstate import DevState
  3. from bootstrap.scd import bootstrap_scd
  4. from uuid import UUID
  5. from services.scd import SCD
  6. from framework.conformance import Conformance
  7. from services.od import OD
  8. from transformation.ramify import ramify
  9. from transformation import rewriter
  10. from services.bottom.V0 import Bottom
  11. from services.primitives.integer_type import Integer
  12. from pattern_matching import mvs_adapter
  13. from pattern_matching.matcher import MatcherVF2
  14. from renderer import plantuml
  15. import sys
  16. def create_integer_node(state, i: int):
  17. node = state.create_node()
  18. integer_t = Integer(node, state)
  19. integer_t.create(i)
  20. return node
  21. def main():
  22. state = DevState()
  23. root = state.read_root() # id: 0
  24. scd_mm_id = bootstrap_scd(state)
  25. int_mm_id = UUID(state.read_value(state.read_dict(state.read_root(), "Integer")))
  26. string_mm_id = UUID(state.read_value(state.read_dict(state.read_root(), "String")))
  27. # def print_tree(root, max_depth, depth=0):
  28. # print(" "*depth, "root=", root, "value=", state.read_value(root))
  29. # src,tgt = state.read_edge(root)
  30. # if src != None:
  31. # print(" "*depth, "src...")
  32. # print_tree(src, max_depth, depth+1)
  33. # if tgt != None:
  34. # print(" "*depth, "tgt...")
  35. # print_tree(tgt, max_depth, depth+1)
  36. # for edge in state.read_outgoing(root):
  37. # for edge_label in state.read_outgoing(edge):
  38. # [_,tgt] = state.read_edge(edge_label)
  39. # label = state.read_value(tgt)
  40. # print(" "*depth, " key:", label)
  41. # [_, tgt] = state.read_edge(edge)
  42. # value = state.read_value(tgt)
  43. # if value != None:
  44. # print(" "*depth, " ->", tgt, " (value:", value, ")")
  45. # else:
  46. # print(" "*depth, " ->", tgt)
  47. # if depth < max_depth:
  48. # if isinstance(value, str) and len(value) == 36:
  49. # i = None
  50. # try:
  51. # i = UUID(value)
  52. # except ValueError as e:
  53. # # print("invalid UUID:", value)
  54. # pass
  55. # if i != None:
  56. # print_tree(i, max_depth, depth+1)
  57. # print_tree(tgt, max_depth, depth+1)
  58. # Meta-model for our DSL
  59. dsl_mm_id = state.create_node()
  60. dsl_mm_scd = SCD(dsl_mm_id, state)
  61. dsl_mm_scd.create_class("Animal", abstract=True)
  62. dsl_mm_scd.create_class("Man", min_c=1, max_c=2)
  63. dsl_mm_scd.create_inheritance("Man", "Animal")
  64. dsl_mm_scd.create_model_ref("Integer", int_mm_id)
  65. dsl_mm_scd.create_attribute_link("Man", "Integer", "weight", optional=False)
  66. dsl_mm_scd.create_class("Bear")
  67. dsl_mm_scd.create_inheritance("Bear", "Animal")
  68. dsl_mm_scd.create_association("afraidOf", "Man", "Animal",
  69. # Every Man afraid of at least one Animal:
  70. src_min_c=0,
  71. src_max_c=None,
  72. tgt_min_c=1,
  73. tgt_max_c=None,
  74. )
  75. print(dsl_mm_scd.list_elements())
  76. conf = Conformance(state, dsl_mm_id, scd_mm_id)
  77. print("conforms?", conf.check_nominal(log=True))
  78. # Model in our DSL
  79. dsl_m_id = state.create_node()
  80. dsl_m_od = OD(dsl_mm_id, dsl_m_id, state)
  81. # dsl_m_od.create_object("animal", "Animal")
  82. dsl_m_od.create_object("george", "Man")
  83. dsl_m_od.create_slot("weight", "george",
  84. dsl_m_od.create_integer_value("george.weight", 80))
  85. # "george_weight"
  86. dsl_m_od.create_object("bear1", "Bear")
  87. dsl_m_od.create_object("bear2", "Bear")
  88. dsl_m_od.create_link("georgeAfraidOfBear1", "afraidOf", "george", "bear1")
  89. dsl_m_od.create_link("georgeAfraidOfBear2", "afraidOf", "george", "bear2")
  90. conf2 = Conformance(state, dsl_m_id, dsl_mm_id)
  91. print("DSL instance conforms?", conf2.check_nominal(log=True))
  92. print(conf2.type_mapping)
  93. # RAMify MM
  94. prefix = "RAM_" # all ramified types can be prefixed to distinguish them a bit more
  95. ramified_mm_id = ramify(state, dsl_mm_id, prefix)
  96. # LHS of our rule
  97. lhs_id = state.create_node()
  98. lhs_od = OD(ramified_mm_id, lhs_id, state)
  99. lhs_od.create_object("man", prefix+"Man")
  100. lhs_od.create_slot(prefix+"weight", "man", lhs_od.create_string_value(f"man.{prefix}weight", 'v < 99'))
  101. lhs_od.create_object("scaryAnimal", prefix+"Animal")
  102. lhs_od.create_link("manAfraidOfAnimal", prefix+"afraidOf", "man", "scaryAnimal")
  103. conf3 = Conformance(state, lhs_id, ramified_mm_id)
  104. print("LHS conforms?", conf3.check_nominal(log=True))
  105. # RHS of our rule
  106. rhs_id = state.create_node()
  107. rhs_od = OD(ramified_mm_id, rhs_id, state)
  108. rhs_od.create_object("man", prefix+"Man")
  109. rhs_od.create_slot(prefix+"weight", "man", rhs_od.create_string_value(f"man.{prefix}weight", 'v + 5'))
  110. rhs_od.create_object("bill", prefix+"Man")
  111. rhs_od.create_slot(prefix+"weight", "bill", rhs_od.create_string_value(f"bill.{prefix}weight", '100'))
  112. rhs_od.create_link("billAfraidOfMan", prefix+"afraidOf", "bill", "man")
  113. conf4 = Conformance(state, rhs_id, ramified_mm_id)
  114. print("RHS conforms?", conf4.check_nominal(log=True))
  115. def render_ramification():
  116. uml = (""
  117. # Render original and RAMified meta-models
  118. + plantuml.render_package("Meta-Model", plantuml.render_class_diagram(state, dsl_mm_id))
  119. + plantuml.render_package("RAMified Meta-Model", plantuml.render_class_diagram(state, ramified_mm_id))
  120. # Render RAMification traceability links
  121. + plantuml.render_trace_ramifies(state, dsl_mm_id, ramified_mm_id)
  122. )
  123. # Render pattern
  124. uml += plantuml.render_package("LHS", plantuml.render_object_diagram(state, lhs_id, ramified_mm_id))
  125. uml += plantuml.render_trace_conformance(state, lhs_id, ramified_mm_id)
  126. # Render pattern
  127. uml += plantuml.render_package("RHS", plantuml.render_object_diagram(state, rhs_id, ramified_mm_id))
  128. uml += plantuml.render_trace_conformance(state, rhs_id, ramified_mm_id)
  129. return uml
  130. def render_all_matches():
  131. uml = render_ramification()
  132. # Render host graph (before rewriting)
  133. uml += plantuml.render_package("Model (before rewrite)", plantuml.render_object_diagram(state, dsl_m_id, dsl_mm_id))
  134. # Render conformance
  135. uml += plantuml.render_trace_conformance(state, dsl_m_id, dsl_mm_id)
  136. print("matching...")
  137. generator = mvs_adapter.match_od(state, dsl_m_id, dsl_mm_id, lhs_id, ramified_mm_id)
  138. for name_mapping, color in zip(generator, ["red", "orange"]):
  139. print("\nMATCH:\n", name_mapping)
  140. # Render every match
  141. uml += plantuml.render_trace_match(state, name_mapping, lhs_id, dsl_m_id, color)
  142. print("DONE")
  143. return uml
  144. def render_rewrite():
  145. uml = render_ramification()
  146. generator = mvs_adapter.match_od(state, dsl_m_id, dsl_mm_id, lhs_id, ramified_mm_id)
  147. for name_mapping in generator:
  148. rewriter.rewrite(state, lhs_id, rhs_id, ramified_mm_id, name_mapping, dsl_m_id, dsl_mm_id)
  149. # Render match
  150. uml_match = plantuml.render_trace_match(state, name_mapping, rhs_id, dsl_m_id)
  151. # Stop matching after rewrite
  152. break
  153. # Render host graph (after rewriting)
  154. uml += plantuml.render_package("Model (after rewrite)", plantuml.render_object_diagram(state, dsl_m_id, dsl_mm_id))
  155. # Render conformance
  156. uml += plantuml.render_trace_conformance(state, dsl_m_id, dsl_mm_id)
  157. uml += uml_match
  158. return uml
  159. conf5 = Conformance(state, dsl_m_id, dsl_mm_id)
  160. print("Updated model conforms?", conf5.check_nominal(log=True))
  161. print()
  162. print("==============================================")
  163. print(render_all_matches())
  164. # print(render_rewrite())
  165. if __name__ == "__main__":
  166. main()