bootstrap.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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. initial_code_manager = "bootstrap/initial_code_manager.alb"
  10. initial_code_task = "bootstrap/initial_code_task.alb"
  11. bootstrap_files = glob.glob("bootstrap/*.alc") + [initial_code_manager, initial_code_task]
  12. task_data = [ "input",
  13. "output",
  14. "globals",
  15. "frame",
  16. ]
  17. task_frame = [ "evalstack",
  18. "symbols",
  19. "returnvalue",
  20. ]
  21. primitives = { "integer_addition": ["Integer", "Integer", "Integer"],
  22. "integer_subtraction": ["Integer", "Integer", "Integer"],
  23. "integer_multiplication": ["Integer", "Integer", "Integer"],
  24. "integer_division": ["Integer", "Integer", "Integer"],
  25. "integer_gt": ["Boolean", "Integer", "Integer"],
  26. "integer_lt": ["Boolean", "Integer", "Integer"],
  27. "integer_neg": ["Integer", "Integer"],
  28. "float_addition": ["Float", "Float", "Float"],
  29. "float_subtraction": ["Float", "Float", "Float"],
  30. "float_multiplication": ["Float", "Float", "Float"],
  31. "float_division": ["Float", "Float", "Float"],
  32. "float_gt": ["Boolean", "Float", "Float"],
  33. "float_lt": ["Boolean", "Float", "Float"],
  34. "float_neg": ["Float", "Float"],
  35. "bool_and": ["Boolean", "Boolean", "Boolean"],
  36. "bool_or": ["Boolean", "Boolean", "Boolean"],
  37. "bool_not": ["Boolean", "Boolean"],
  38. "string_join": ["String", "String", "String"],
  39. "string_get": ["String", "String", "Integer"],
  40. "string_len": ["Integer", "String"],
  41. "string_split": ["Element", "String", "String"],
  42. "value_eq": ["Boolean", "Element", "Element"],
  43. "value_neq": ["Boolean", "Element", "Element"],
  44. "cast_i2f": ["Float", "Integer"],
  45. "cast_i2s": ["String", "Integer"],
  46. "cast_i2b": ["Boolean", "Integer"],
  47. "cast_f2i": ["Integer", "Float"],
  48. "cast_f2b": ["Boolean", "Float"],
  49. "cast_f2s": ["String", "Float"],
  50. "cast_s2i": ["Integer", "String"],
  51. "cast_s2f": ["Float", "String"],
  52. "cast_s2b": ["Boolean", "String"],
  53. "cast_b2i": ["Integer", "Boolean"],
  54. "cast_b2f": ["Float", "Boolean"],
  55. "cast_b2s": ["String", "Boolean"],
  56. "cast_e2s": ["String", "Element"],
  57. "cast_a2s": ["String", "Action"],
  58. "cast_v2s": ["String", "Element"],
  59. "cast_id2s": ["String", "Element"],
  60. "list_read": ["Element", "Element", "Integer"],
  61. "list_append": ["Element", "Element", "Element"],
  62. "list_insert": ["Element", "Element", "Integer", "Element"],
  63. "list_delete": ["Element", "Element", "Integer"],
  64. "list_len": ["Integer", "Element"],
  65. "dict_add": ["Element", "Element", "Element", "Element"],
  66. "dict_add_fast": ["Element", "Element", "Element", "Element"],
  67. "dict_delete": ["Element", "Element", "Element"],
  68. "dict_delete_node": ["Element", "Element", "Element"],
  69. "dict_read": ["Element", "Element", "Element"],
  70. "dict_read_edge": ["Element", "Element", "Element"],
  71. "dict_read_node": ["Element", "Element", "Element"],
  72. "dict_len": ["Integer", "Element"],
  73. "dict_in": ["Boolean", "Element", "Element"],
  74. "dict_in_node": ["Boolean", "Element", "Element"],
  75. "dict_keys": ["Element", "Element"],
  76. "set_add": ["Element", "Element", "Element"],
  77. "set_pop": ["Element", "Element"],
  78. "set_remove": ["Element", "Element", "Element"],
  79. "set_remove_node": ["Element", "Element", "Element"],
  80. "set_in": ["Boolean", "Element", "Element"],
  81. "set_in_node": ["Boolean", "Element", "Element"],
  82. "is_physical_int": ["Boolean", "Element"],
  83. "is_physical_boolean": ["Boolean", "Element"],
  84. "is_physical_string": ["Boolean", "Element"],
  85. "is_physical_action": ["Boolean", "Element"],
  86. "is_physical_float": ["Boolean", "Element"],
  87. "create_node": ["Element"],
  88. "create_edge": ["Element", "Element", "Element"],
  89. "create_value": ["Element", "Element"],
  90. "is_edge": ["Boolean", "Element"],
  91. "read_nr_out": ["Integer", "Element"],
  92. "read_out": ["Element", "Element", "Integer"],
  93. "read_nr_in": ["Integer", "Element"],
  94. "read_in": ["Element", "Element", "Integer"],
  95. "read_edge_src": ["Element", "Element"],
  96. "read_edge_dst": ["Element", "Element"],
  97. "delete_element": ["Element", "Element"],
  98. "element_eq": ["Boolean", "Element", "Element"],
  99. "element_neq": ["Boolean", "Element", "Element"],
  100. "read_root": ["Element"],
  101. "read_taskroot": ["Element"],
  102. "deserialize": ["Element", "String"],
  103. "log": ["String", "String"],
  104. "time": ["Float"],
  105. "hash": ["String", "String"],
  106. }
  107. jit_primitives = {
  108. "get_jit_enabled": ["Boolean"],
  109. "set_jit_enabled": ["Void", "Boolean"]
  110. }
  111. ### Actual script to generate the file
  112. import os
  113. import sys
  114. class Writer(object):
  115. def __init__(self, file_a, file_b):
  116. self.file_a = file_a
  117. self.file_b = file_b
  118. def write(self, text, both=True):
  119. self.file_a.write(text)
  120. if both:
  121. self.file_b.write(text)
  122. try:
  123. with gzip.GzipFile("bootstrap/bootstrap.m.gz", "wb", mtime=0) as fa:
  124. with gzip.GzipFile("bootstrap/minimal.m.gz", "wb", mtime=0) as fb:
  125. f = Writer(fa, fb)
  126. # Create the root first
  127. f.write("Node root()\n")
  128. # Create all children of the root
  129. for node in root:
  130. f.write("Node %s()\n" % node)
  131. f.write("Dict (root, \"%s\", %s)\n" % (node, node))
  132. def declare_primitive_class(primitive_class_name, primitive_decls):
  133. f.write("Node %s()\n" % primitive_class_name)
  134. f.write("Dict (__hierarchy, \"%s\", %s)\n" % (primitive_class_name, primitive_class_name))
  135. # Define all primitive functions
  136. for function, parameters in primitive_decls.iteritems():
  137. f.write("Node _func_signature_%s()\n" % function)
  138. f.write("Node _func_params_%s()\n" % function)
  139. f.write("Node _func_body_%s()\n" % function)
  140. f.write('Dict (%s, "%s", _func_signature_%s)\n' % (primitive_class_name, function, function))
  141. f.write('Dict (_func_signature_%s, "body", _func_body_%s)\n' % (function, function))
  142. f.write('Dict (_func_signature_%s, "params", _func_params_%s)\n' % (function, function))
  143. parameter_names = "abcdefghijklmnopqrstuvwxyz"
  144. for number, param in enumerate(parameters[1:]):
  145. param_encoding = "%s_%s" % (function, parameter_names[number])
  146. f.write("Node _func_params_%s()\n" % (param_encoding))
  147. f.write('Node _name_%s("%s")\n' % (param_encoding, parameter_names[number]))
  148. f.write("Edge _param_link_%s(_func_params_%s, _func_params_%s)\n" % (param_encoding, function, param_encoding))
  149. f.write("Edge _param_link_str_%s(_param_link_%s, _name_%s)\n" % (param_encoding, param_encoding, param_encoding))
  150. f.write('Node _name_str_%s("name")\n' % param_encoding)
  151. f.write("Edge _param_name_%s(_func_params_%s, _name_%s)\n" % (param_encoding, param_encoding, param_encoding))
  152. f.write("Edge _param_name_str_%s(_param_name_%s, _name_str_%s)\n" % (param_encoding, param_encoding, param_encoding))
  153. declare_primitive_class('primitives', primitives)
  154. declare_primitive_class('jit', jit_primitives)
  155. # Create the initial task
  156. f.write("Node task_root()\n")
  157. for data in task_data:
  158. f.write("Node task_%s()\n" % data)
  159. f.write('Dict (task_root, "%s", task_%s)\n' % (data, data))
  160. for data in task_frame:
  161. f.write("Node task_%s()\n" % data)
  162. f.write('Dict (task_frame, "%s", task_%s)\n' % (data, data))
  163. # Add last_input and last_output links
  164. for data in ["input", "output"]:
  165. f.write('Dict (task_root, "last_%s", task_%s)\n' % (data, data))
  166. # Bind task to the root
  167. f.write('Dict (root, "%s", task_root)\n' % (task_manager))
  168. def compile_code_AL(filename, target, prepend="", main=False, symbols=None):
  169. import sys
  170. sys.path.append("interface/HUTN/")
  171. from hutn_compiler.compiler import main as compile_code
  172. code = compile_code(filename, "interface/HUTN/grammars/actionlanguage.g", "BS", ["--debug", "--prepend:%s" % prepend, "--main" if main else "--not-main"], symbols=symbols)
  173. return code.replace("auto_initial_IP", target)
  174. # Create all library code
  175. # But first create the structure to hold compiled data
  176. f.write("Node __objects()\n", both=False)
  177. f.write('Dict (__hierarchy, "objects", __objects)\n', both=False)
  178. # Compile all files and add to structure manually
  179. for bootstrap_file in bootstrap_files:
  180. # Compile the subfile
  181. bootstrap_file = bootstrap_file.replace("\\", "/")
  182. print("[COMP] %s" % bootstrap_file)
  183. symbols = {}
  184. f.write(compile_code_AL(bootstrap_file, "initial_IP", prepend=bootstrap_file, symbols=symbols, main = bootstrap_file in [initial_code_manager, initial_code_task]), both=False)
  185. # Now link the code with the compilation manager structure
  186. f.write("Node elem()\n", both=False)
  187. f.write('Dict (__objects, "%s", elem)\n' % bootstrap_file, both=False)
  188. f.write('Dict (elem, "initializers", %s_initial_IP)\n' % bootstrap_file, both=False)
  189. md5 = hashlib.md5()
  190. md5.update(open(bootstrap_file, 'r').read())
  191. f.write('Node hash_value("%s")\n' % md5.hexdigest(), both=False)
  192. f.write('Dict (elem, "hash_md5", hash_value)\n', both=False)
  193. f.write('Node __symbols()\n', both=False)
  194. f.write('Dict (elem, "symbols", __symbols)\n', both=False)
  195. for k, v in symbols.items():
  196. f.write('Node v(%s)\n' % v, both=False)
  197. f.write('Dict (__symbols, "%s", v)\n' % (k), both=False)
  198. # Create code for initial task
  199. print("[BOOT] task_manager")
  200. f.write('Dict (task_frame, "IP", %s_initial_IP)\n' % (initial_code_manager), both=False)
  201. f.write('Node __phase("init")\n', both=False)
  202. f.write('Dict (task_frame, "phase", __phase)\n', both=False)
  203. # Create code for new tasks to start at
  204. print("[BOOT] new_task")
  205. f.write('Dict (__hierarchy, "__IP", %s_initial_IP)\n' % initial_code_task, both=False)
  206. except:
  207. os.remove("bootstrap/bootstrap.m.gz")
  208. os.remove("bootstrap/minimal.m.gz")
  209. raise