runner_translate.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. from state.devstate import DevState
  2. from bootstrap.scd import bootstrap_scd
  3. from concrete_syntax.textual_od import parser, renderer
  4. from concrete_syntax.plantuml.renderer import render_object_diagram, render_class_diagram
  5. from concrete_syntax.plantuml.make_url import make_url
  6. from api.od import ODAPI
  7. from transformation.ramify import ramify
  8. from transformation.rule import RuleMatcherRewriter
  9. from util import loader
  10. from util.module_to_dict import module_to_dict
  11. from examples.semantics.operational.port import models, helpers
  12. from examples.semantics.operational.port.renderer import render_port_textual, render_port_graphviz
  13. from examples.semantics.translational.renderer import show_port_and_petri_net
  14. from examples.petrinet.renderer import render_petri_net
  15. import os
  16. THIS_DIR = os.path.dirname(__file__)
  17. # get file contents as string
  18. def read_file(filename):
  19. with open(THIS_DIR+'/'+filename) as file:
  20. return file.read()
  21. if __name__ == "__main__":
  22. state = DevState()
  23. scd_mmm = bootstrap_scd(state)
  24. print('loading merged MM...')
  25. merged_mm = loader.parse_and_check(state, read_file("merged_mm.od"), scd_mmm, "merged_mm.od",
  26. check_conformance=False, # no need to check conformance every time
  27. )
  28. print('ramifying...')
  29. ramified_merged_mm = ramify(state, merged_mm)
  30. ###################################
  31. # This is the main part you want to edit (by adding/changing the transformation rules)
  32. # | | |
  33. # V V V
  34. rule_names = [
  35. # high to low priority (the list-order here matters, the alphabetic-order of the names does not):
  36. "00_place2place",
  37. "10_conn2trans",
  38. # The above two rules create a bunch of PN places and PN transitions.
  39. # (with generic_links to the Port-elements)
  40. # One way to continue, is to create PN arcs between the places and transitions.
  41. # Or you can also just start from scratch, if you have a better idea :)
  42. ]
  43. # The script below will keep executing the first rule until it no longer matches, then the second rule, etc.
  44. ###################################
  45. print('loading rules...')
  46. rules = loader.load_rules(state,
  47. lambda rule_name, kind: f"{THIS_DIR}/rules/gen_pn/r_{rule_name}_{kind}.od",
  48. ramified_merged_mm,
  49. rule_names)
  50. print('loading model...')
  51. port_m_rt_initial = loader.parse_and_check(state,
  52. m_cs=models.port_rt_m_cs, # <-- your final solution should work with the full model
  53. # m_cs=models.smaller_model_rt_cs, # <-- simpler model to try first
  54. # m_cs=models.smaller_model2_rt_cs, # <-- simpler model to try first
  55. mm=merged_mm,
  56. descr="initial model",
  57. check_conformance=False, # no need to check conformance every time
  58. )
  59. print('ready!')
  60. port_m_rt = port_m_rt_initial
  61. eval_context = {
  62. # make all the functions defined in 'helpers' module available to 'condition'-code in LHS/NAC/RHS:
  63. **module_to_dict(helpers),
  64. # another example: in all 'condition'-code, there will be a global variable 'meaning_of_life', equal to 42:
  65. 'meaning_of_life': 42, # just to demonstrate - feel free to remove this
  66. }
  67. print('The following additional globals are available:', ', '.join(list(eval_context.keys())))
  68. matcher_rewriter = RuleMatcherRewriter(state, merged_mm, ramified_merged_mm, eval_context=eval_context)
  69. ###################################
  70. # Because the matching of many different rules can be slow,
  71. # this script will store intermediate snapshots each time
  72. # after having 'exhausted' a rule.
  73. # When re-running the script, the stored snapshots will be loaded
  74. # from disk instead of re-running the rules.
  75. # You can force re-running the rules (e.g., because you changed the rules)
  76. # by deleting the `snapshot_after_*` files.
  77. ###################################
  78. ###################################
  79. # You are allowed to edit the script below, but you don't have to.
  80. # Changes you may want to make:
  81. # - outcomment the 'render_petri_net'-call (preventing popups)
  82. # - if you really want to do something crazy,
  83. # you can even write a script that uses the lower-level `match_od`/`rewrite` primitives...
  84. # - ??
  85. ###################################
  86. for i, rule_name in enumerate(rule_names):
  87. filename = f"{THIS_DIR}/snapshot_after_{rule_name}.od"
  88. print("rule =", rule_name)
  89. rule = rules[rule_name]
  90. try:
  91. with open(filename, "r") as file:
  92. port_m_rt = parser.parse_od(state, file.read(), merged_mm)
  93. print(f'skip rule (found {filename})')
  94. except FileNotFoundError:
  95. # Fire every rule until it cannot match any longer:
  96. while True:
  97. result = matcher_rewriter.exec_on_first_match(port_m_rt, rule, rule_name,
  98. in_place=True, # faster
  99. )
  100. if result == None:
  101. print(" no matches")
  102. break
  103. else:
  104. port_m_rt, lhs_match, _ = result
  105. print(" rewrote", lhs_match)
  106. txt = renderer.render_od(state, port_m_rt, merged_mm)
  107. with open(filename, "w") as file:
  108. file.write(txt)
  109. print('wrote', filename)
  110. render_petri_net(ODAPI(state, port_m_rt, merged_mm))
  111. # Uncomment to show also the port model:
  112. # show_port_and_petri_net(state, port_m_rt, merged_mm)
  113. # Uncomment to pause after each rendering:
  114. # input()
  115. ###################################
  116. # Once you have generated a Petri Net, you can execute the petri net:
  117. #
  118. # python runner_exec_pn.py snapshot_after_XX_name_of_my_last_rule.od
  119. ###################################