bootstrap.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. ### Configuration for creating the bootstrap model using conformance_bottom.
  2. import glob
  3. import hashlib
  4. import tempfile
  5. import gzip
  6. def bootstrap():
  7. root = ["__hierarchy"]
  8. task_manager = "task_manager"
  9. main_file = "bootstrap/main.alc"
  10. primitive_file = "bootstrap/primitives.alc"
  11. task_data = [ "input",
  12. "output",
  13. "globals",
  14. "frame",
  15. ]
  16. task_frame = [ "evalstack",
  17. "returnvalue",
  18. "symbols",
  19. ]
  20. primitives = { "integer_addition": ["Integer", "Integer", "Integer"],
  21. "integer_subtraction": ["Integer", "Integer", "Integer"],
  22. "integer_multiplication": ["Integer", "Integer", "Integer"],
  23. "integer_division": ["Integer", "Integer", "Integer"],
  24. "integer_lt": ["Boolean", "Integer", "Integer"],
  25. "float_addition": ["Float", "Float", "Float"],
  26. "float_subtraction": ["Float", "Float", "Float"],
  27. "float_multiplication": ["Float", "Float", "Float"],
  28. "float_division": ["Float", "Float", "Float"],
  29. "float_lt": ["Boolean", "Float", "Float"],
  30. "bool_and": ["Boolean", "Boolean", "Boolean"],
  31. "bool_or": ["Boolean", "Boolean", "Boolean"],
  32. "bool_not": ["Boolean", "Boolean"],
  33. "string_join": ["String", "String", "String"],
  34. "string_get": ["String", "String", "Integer"],
  35. "string_len": ["Integer", "String"],
  36. "string_split": ["Element", "String", "String"],
  37. "value_eq": ["Boolean", "Element", "Element"],
  38. "cast_float": ["Float", "Element"],
  39. "cast_string": ["String", "Element"],
  40. "cast_boolean": ["Boolean", "Element"],
  41. "cast_integer": ["Integer", "Element"],
  42. "cast_value": ["String", "Element"],
  43. "cast_id": ["String", "Element"],
  44. "dict_add_fast": ["Element", "Element", "Element", "Element"],
  45. "dict_delete": ["Element", "Element", "Element"],
  46. "dict_delete_node": ["Element", "Element", "Element"],
  47. "dict_read": ["Element", "Element", "Element"],
  48. "dict_read_edge": ["Element", "Element", "Element"],
  49. "dict_read_node": ["Element", "Element", "Element"],
  50. "dict_in": ["Boolean", "Element", "Element"],
  51. "dict_in_node": ["Boolean", "Element", "Element"],
  52. "dict_keys": ["Element", "Element"],
  53. "is_physical_int": ["Boolean", "Element"],
  54. "is_physical_boolean": ["Boolean", "Element"],
  55. "is_physical_string": ["Boolean", "Element"],
  56. "is_physical_action": ["Boolean", "Element"],
  57. "is_physical_float": ["Boolean", "Element"],
  58. "is_physical_none": ["Boolean", "Element"],
  59. "create_node": ["Element"],
  60. "create_edge": ["Element", "Element", "Element"],
  61. "create_value": ["Element", "Element"],
  62. "is_edge": ["Boolean", "Element"],
  63. "is_error": ["Boolean", "Element"],
  64. "read_nr_out": ["Integer", "Element"],
  65. "read_out": ["Element", "Element", "Integer"],
  66. "read_nr_in": ["Integer", "Element"],
  67. "read_in": ["Element", "Element", "Integer"],
  68. "read_edge_src": ["Element", "Element"],
  69. "read_edge_dst": ["Element", "Element"],
  70. "delete_element": ["Element", "Element"],
  71. "element_eq": ["Boolean", "Element", "Element"],
  72. "read_root": ["Element"],
  73. "read_taskroot": ["Element"],
  74. "list_sort": ["Element", "Element"],
  75. "log": ["String", "String"],
  76. "time": ["Float"],
  77. "hash": ["String", "String"],
  78. "__sleep": ["Float", "Float", "Boolean"],
  79. }
  80. jit_primitives = {
  81. "get_jit_enabled": ["Boolean"],
  82. "set_jit_enabled": ["Void", "Boolean"]
  83. }
  84. ### Actual script to generate the file
  85. import os
  86. import sys
  87. class Writer(object):
  88. def __init__(self, file_a, file_b):
  89. self.file_a = file_a
  90. self.file_b = file_b
  91. def write(self, text, both=True):
  92. if sys.version_info[0] > 2:
  93. text = text.encode()
  94. self.file_a.write(text)
  95. if both:
  96. self.file_b.write(text)
  97. try:
  98. with gzip.GzipFile("bootstrap/bootstrap.m.gz", "wb", mtime=0) as fa:
  99. with gzip.GzipFile("bootstrap/minimal.m.gz", "wb", mtime=0) as fb:
  100. f = Writer(fa, fb)
  101. # Create the root first
  102. f.write("Node root()\n")
  103. # Create all children of the root
  104. for node in root:
  105. f.write("Node %s()\n" % node)
  106. f.write("Dict (root, \"%s\", %s)\n" % (node, node))
  107. def declare_primitive_class(primitive_class_name, primitive_decls):
  108. f.write("Node %s()\n" % primitive_class_name)
  109. f.write("Dict (__hierarchy, \"%s\", %s)\n" % (primitive_class_name, primitive_class_name))
  110. # Define all primitive functions
  111. for function, parameters in list(primitive_decls.items()):
  112. f.write("Node _func_signature_%s()\n" % function)
  113. f.write("Node _func_params_%s()\n" % function)
  114. f.write("Node _func_body_%s()\n" % function)
  115. f.write('Dict (%s, "%s", _func_signature_%s)\n' % (primitive_class_name, function, function))
  116. f.write('Dict (_func_signature_%s, "body", _func_body_%s)\n' % (function, function))
  117. f.write('Dict (_func_signature_%s, "params", _func_params_%s)\n' % (function, function))
  118. parameter_names = "abcdefghijklmnopqrstuvwxyz"
  119. for number, param in enumerate(parameters[1:]):
  120. param_encoding = "%s_%s" % (function, parameter_names[number])
  121. f.write("Node _func_params_%s()\n" % (param_encoding))
  122. f.write('Node _name_%s("%s")\n' % (param_encoding, parameter_names[number]))
  123. #f.write("Edge _param_link_%s(_func_params_%s, _func_params_%s)\n" % (param_encoding, function, param_encoding))
  124. #f.write("Edge _param_link_str_%s(_param_link_%s, _name_%s)\n" % (param_encoding, param_encoding, param_encoding))
  125. f.write('Dict (_func_params_%s, "%s", _func_params_%s)\n' % (function, parameter_names[number], param_encoding))
  126. #f.write('Node _name_str_%s("name")\n' % param_encoding)
  127. #f.write("Edge _param_name_%s(_func_params_%s, _name_%s)\n" % (param_encoding, param_encoding, param_encoding))
  128. #f.write("Edge _param_name_str_%s(_param_name_%s, _name_str_%s)\n" % (param_encoding, param_encoding, param_encoding))
  129. f.write('Dict (_func_params_%s, "name", _name_%s)\n' % (param_encoding, param_encoding))
  130. declare_primitive_class('primitives', primitives)
  131. declare_primitive_class('jit', jit_primitives)
  132. # Create the initial task
  133. f.write("Node task_root()\n")
  134. for data in task_data:
  135. f.write("Node task_%s()\n" % data)
  136. f.write('Dict (task_root, "%s", task_%s)\n' % (data, data))
  137. for data in task_frame:
  138. f.write("Node task_%s()\n" % data)
  139. f.write('Dict (task_frame, "%s", task_%s)\n' % (data, data))
  140. # Add last_input and last_output links
  141. for data in ["input", "output"]:
  142. f.write('Dict (task_root, "last_%s", task_%s)\n' % (data, data))
  143. # Bind task to the root
  144. f.write('Dict (root, "%s", task_root)\n' % (task_manager))
  145. def compile_code_AL(filename, target, prepend="", main=False):
  146. import sys
  147. sys.path.append("interface/HUTN/")
  148. from hutn_compiler.compiler import main as compile_code
  149. code = compile_code(filename, "interface/HUTN/grammars/actionlanguage.g", "BS", ["--debug", "--prepend:%s" % prepend, "--main" if main else "--not-main"])
  150. return code.replace("auto_initial_IP", target)
  151. # Create all library code
  152. def compile_code_MO(filename, model_name):
  153. import sys
  154. sys.path.append("interface/HUTN/")
  155. from hutn_compiler.compiler import main as compile_code
  156. model_code = compile_code(filename, "interface/HUTN/grammars/modelling_bootstrap.g", "MB", ["--modelname:%s" % model_name])
  157. return model_code + "\n"
  158. # Compile all model definitions to ALC directly
  159. single_file = ""
  160. total_alc = []
  161. binding_alc = 'Void function initialize_MMs():\n\tinitialize_SCD("models/SimpleClassDiagrams")\n'
  162. bootstrap_models = sorted(glob.glob("bootstrap/*.mvc"))
  163. for bootstrap_model in bootstrap_models:
  164. # Compile the subfile
  165. bootstrap_model = bootstrap_model.replace("\\", "/")
  166. model_name = bootstrap_model.rsplit(".mvc", 1)[0].rsplit("/", 1)[1]
  167. print("[MVC] %s" % model_name)
  168. alc = compile_code_MO(bootstrap_model, model_name)
  169. total_alc.append(alc)
  170. binding_alc += "\tinitialize_%s()\n" % model_name
  171. total_alc = "".join(total_alc)
  172. # Write out the ALC to a new .metamodels.alc
  173. binding_alc += "\treturn!\n"
  174. new_metamodels_alc = open("bootstrap/metamodels.alt", 'r').read() + total_alc + binding_alc
  175. # Now overwrite the .metamodels.alc file
  176. with open("bootstrap/.metamodels.alc", "w") as mm:
  177. mm.write(new_metamodels_alc)
  178. # Compile all files and add to structure manually
  179. bootstrap_files = sorted(glob.glob("bootstrap/*.alc") + glob.glob("bootstrap/.*.alc"))
  180. all_code = ""
  181. for bootstrap_file in bootstrap_files:
  182. # Compile the subfile
  183. bootstrap_file = bootstrap_file.replace("\\", "/")
  184. print("[ALC] %s" % bootstrap_file)
  185. all_code += "".join([i.replace(" = ?\n", "\n") for i in open(bootstrap_file, 'r').readlines() if not i.startswith("include ")])
  186. f.write(compile_code_AL(bootstrap_file, "initial_IP", prepend=bootstrap_file, main=bootstrap_file==main_file), both=False)
  187. # TODO all assigns stored in:
  188. # bootstrap_file + "_initial_IP"
  189. # Now link the code with the compilation manager structure
  190. print("[MERGE]")
  191. all_code += "Void function main():\n\tlog(\"INIT\")\n\treturn!"
  192. with open("bootstrap/merged.alm", 'w') as merged:
  193. merged.write(all_code)
  194. # Stitch all IPs together
  195. print("[LINK]")
  196. counter = 0
  197. f.write('Node true(constant)\n', both=False)
  198. f.write('Node t(True)\n', both=False)
  199. f.write('Dict (true, "node", t)\n', both=False)
  200. first = True
  201. for bootstrap_file in [primitive_file] + [i for i in bootstrap_files if i not in [main_file, primitive_file]]:
  202. f.write('Node _if_%s(if)\n' % counter, both=False)
  203. f.write('Dict (_if_%s, "cond", true)\n' % counter, both=False)
  204. f.write('Dict (_if_%s, "then", %s_initial_IP)\n' % (counter, bootstrap_file), both=False)
  205. if first:
  206. first = False
  207. else:
  208. f.write('Dict (%s, "next", _if_%s)\n' % (prev, counter), both=False)
  209. prev = "_if_%s" % counter
  210. counter += 1
  211. f.write('Dict (%s, "next", %s_initial_IP)\n' % (prev, main_file), both=False)
  212. # Create code for initial task
  213. print("[BOOT] task_manager")
  214. f.write('Dict (task_frame, "IP", _if_0)\n', both=False)
  215. f.write('Node __phase("init")\n', both=False)
  216. f.write('Dict (task_frame, "phase", __phase)\n', both=False)
  217. # Create code for new tasks to start at
  218. print("[BOOT] new_task")
  219. f.write('Dict (__hierarchy, "__IP", _if_0)\n', both=False)
  220. except:
  221. os.remove("bootstrap/bootstrap.m.gz")
  222. os.remove("bootstrap/minimal.m.gz")
  223. raise