model_bootstrap_visitor.py 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. from interface.HUTN.hutn_compiler.visitor import Visitor
  2. from interface.HUTN.hutn_compiler.compiler import main as do_compile
  3. import os
  4. import uuid
  5. def empty(s):
  6. return None
  7. class ModelBootstrapVisitor(Visitor):
  8. def __init__(self, args):
  9. Visitor.__init__(self, args)
  10. model_name = [arg.split(":", 1)[1] for arg in args if arg.startswith("--modelname:")][0]
  11. self.code = "Void function initialize_%s():\n" % model_name
  12. self.free_id = 0
  13. self.names = set()
  14. self.current_model = None
  15. self.current_element = []
  16. self.includes = []
  17. def dump(self):
  18. return self.code + "\treturn!"
  19. def __getattr__(self, attr):
  20. if attr.startswith("visit_"):
  21. return empty
  22. else:
  23. raise AttributeError()
  24. def visit_start(self, tree):
  25. for t in tree.get_tail():
  26. self.visit(t)
  27. self.code += '\tdict_overwrite(%s, "types", get_type_mapping(%s))\n' % (self.current_model, self.current_model)
  28. def visit_include_files(self, tree):
  29. self.includes.append('include %s' % tree.get_children("STRVALUE")[0].get_text())
  30. def visit_import(self, tree):
  31. url = tree.get_children("MV_URL")[0]
  32. target = tree.get_children("MODEL_ID")[0]
  33. #self.constructors.extend(["import_node", url.get_text(), target.get_text()])
  34. self.code += '\tElement %s\n' % target.get_text()
  35. self.code += '\t%s = import_node("%s")\n' % (target.get_text(), url.get_text())
  36. def visit_export(self, tree):
  37. url = tree.get_children("MV_URL")[0]
  38. target = tree.get_children("MODEL_ID")[0]
  39. #self.constructors.extend(["export_node", target.get_text(), url.get_text()])
  40. self.code += '\texport_node("%s", %s)\n' % (url.get_text(), target.get_text())
  41. def visit_model(self, tree):
  42. children = tree.get_children("MODEL_ID")
  43. model_type = children[0].get_text()
  44. model_name = children[-1].get_text()
  45. #self.constructors.extend(["instantiate_model", model_type, model_name])
  46. self.code += "\tElement %s\n" % model_name
  47. self.code += '\t%s = instantiate_model(%s)\n' % (model_name, model_type)
  48. self.current_model = model_name
  49. self.names = set()
  50. for element in tree.get_children("model_element"):
  51. self.visit(element)
  52. def visit_model_element(self, tree):
  53. children = tree.get_children("MODEL_ID")
  54. element_type = children[0].get_text()
  55. if len(children) == 2 or len(children) == 4:
  56. element_name = children[1].get_text()
  57. else:
  58. element_name = "__%s" % self.free_id
  59. self.free_id += 1
  60. if element_name in self.names:
  61. raise Exception("Redefinition of element %s" % element_name)
  62. if len(children) > 2:
  63. # So we have a source and target; but aren't sure which is which, because the name is optional!
  64. source_name = children[-2].get_text()
  65. target_name = children[-1].get_text()
  66. if source_name not in self.names:
  67. raise Exception("Source of link %s unknown: %s" % (element_name, source_name))
  68. if target_name not in self.names:
  69. raise Exception("Target of link %s unknown: %s" % (element_name, target_name))
  70. #self.constructors.extend(["instantiate_link", self.current_model, element_type, element_name, source_name, target_name])
  71. self.code += '\tinstantiate_link(%s, "%s", "%s", "%s", "%s")\n' % (self.current_model, element_type, element_name, source_name, target_name)
  72. else:
  73. #self.constructors.extend(["instantiate_node", self.current_model, element_type, element_name])
  74. self.code += '\tinstantiate_node(%s, "%s", "%s")\n' % (self.current_model, element_type, element_name)
  75. self.names.add(element_name)
  76. self.current_element.append(element_name)
  77. if tree.get_children("inheritance"):
  78. self.visit(tree.get_children("inheritance")[0])
  79. for attr in tree.get_children("model_attribute"):
  80. self.visit(attr)
  81. self.current_element.pop()
  82. return element_name
  83. def visit_inheritance(self, tree):
  84. for token in tree.get_children("MODEL_ID"):
  85. superclass = token.get_text()
  86. if superclass not in self.names:
  87. raise Exception("Superclass %s is undefined" % superclass)
  88. #self.constructors.extend(["instantiate_link", self.current_model, "Inheritance", "%s_inherits_from_%s" % (self.current_element[-1], superclass), self.current_element[-1], superclass])
  89. self.code += '\tinstantiate_link(%s, "Inheritance", "%s_inherits_from_%s", "%s", "%s")\n' % (self.current_model, self.current_element[-1], superclass, self.current_element[-1], superclass)
  90. self.names.add("%s_inherits_from_%s" % (self.current_element[-1], superclass))
  91. def visit_model_attribute(self, tree):
  92. children = tree.get_children("MODEL_ID")
  93. is_definition = bool(tree.get_children("COLON"))
  94. is_assign = bool(tree.get_children("model_attr_instance"))
  95. is_nested = bool(tree.get_children("model_element"))
  96. if is_definition:
  97. attr_name = children[0].get_text()
  98. attr_optional = len(tree.get_children("OPTIONAL")) > 0
  99. attr_type = children[1].get_text()
  100. #self.constructors.extend(["model_define_attribute", self.current_model, self.current_element[-1], attr_name, attr_optional, attr_type])
  101. self.code += '\tmodel_define_attribute(%s, "%s", "%s", %s, "%s")\n' % (self.current_model, self.current_element[-1], attr_name, attr_optional, attr_type)
  102. full_attribute_name = self.current_element[-1] + "_" + attr_name
  103. if is_assign:
  104. # There are also some attributes to set!
  105. self.current_element.append(full_attribute_name)
  106. for f in tree.get_children("model_attr_instance"):
  107. self.visit(f)
  108. self.current_element.pop()
  109. elif is_assign:
  110. self.visit(tree.get_children("model_attr_instance")[0])
  111. elif is_nested:
  112. if tree.get_children("MODEL_ID"):
  113. contains_link = tree.get_children("MODEL_ID")[0].get_text()
  114. else:
  115. contains_link = ""
  116. entry = self.visit(tree.get_children("model_element")[0])
  117. #self.constructors.extend(["instantiate_link", self.current_model, contains_link, "__%s" % self.free_id, self.current_element[-1], entry])
  118. self.code += '\tinstantiate_link(%s, "%s", "__%s", "%s", "%s")\n' % (self.current_model, contains_link, self.free_id, self.current_element[-1], entry)
  119. self.names.add("__%s" % self.free_id)
  120. self.free_id += 1
  121. def visit_model_attr_instance(self, tree):
  122. def constructors_compile(code):
  123. code_fragments = code.split("\n")
  124. code_fragments = [i for i in code_fragments if i.strip() != ""]
  125. code_fragments = [i.replace(" ", "\t") for i in code_fragments]
  126. initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments])
  127. code_fragments = self.includes + [i[initial_tabs:] for i in code_fragments]
  128. code = "\n".join(code_fragments)
  129. code += "\n"
  130. with open(".code.alc", 'w') as f:
  131. f.write(code)
  132. f.flush()
  133. directory = os.path.realpath(__file__).rsplit(os.sep, 1)[0]
  134. compiled = do_compile(".code.alc", directory + "/../grammars/actionlanguage.g", "CS")
  135. return compiled
  136. children = tree.get_children("MODEL_ID")
  137. attr_name = children[0].get_text()
  138. if tree.get_children("value"):
  139. # Value attribute
  140. attr_value = tree.get_children("value")[0].get_tail()[0]
  141. if attr_value.head == "STRVALUE":
  142. attr_value = '"%s"' % attr_value.get_text()[1:-1]
  143. elif attr_value.head == "TRUE":
  144. attr_value = True
  145. elif attr_value.head == "FALSE":
  146. attr_value = False
  147. elif attr_value.head == "DEC_NUMBER":
  148. attr_value = int(attr_value.get_text())
  149. elif attr_value.head == "FLOAT_NUMBER":
  150. attr_value = float(attr_value.get_text())
  151. else:
  152. raise Exception(attr_value.head)
  153. #self.constructors.extend(["instantiate_attribute", self.current_model, self.current_element[-1], attr_name, attr_value])
  154. self.code += '\tinstantiate_attribute(%s, "%s", "%s", %s)\n' % (self.current_model, self.current_element[-1], attr_name, attr_value)
  155. elif tree.get_children("DOLLAR"):
  156. # Coded attribute
  157. #self.constructors.extend(["instantiate_attribute_code", self.current_model, self.current_element[-1], attr_name])
  158. #self.constructors.extend(constructors_compile(tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()))
  159. code = tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()
  160. code_fragments = code.split("\n")
  161. code_fragments = [i for i in code_fragments if i.strip() != ""]
  162. code_fragments = [i.replace(" ", "\t") for i in code_fragments]
  163. initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments])
  164. code_fragments = [i[initial_tabs:] for i in code_fragments]
  165. code_fragments.append("")
  166. code = "\n".join(code_fragments)
  167. func_name = "__code__%s" % abs(hash(code))
  168. self.code += '\tinstantiate_attribute_code(%s, "%s", "%s", %s)\n' % (self.current_model, self.current_element[-1], attr_name, func_name)
  169. # Rewrite the name of the function to func_name
  170. prepend = code
  171. before, after = prepend.split("function ", 1)
  172. before = before + "function "
  173. after = "(" + after.split("(", 1)[1]
  174. prepend = before + func_name + after + "\n"
  175. # And prepend the actual code block
  176. self.code = prepend + self.code