|
@@ -0,0 +1,205 @@
|
|
|
+from visitor import Visitor
|
|
|
+from compiler import main as do_compile
|
|
|
+import os
|
|
|
+import uuid
|
|
|
+
|
|
|
+def empty(s):
|
|
|
+ return None
|
|
|
+
|
|
|
+class ModelBootstrapVisitor(Visitor):
|
|
|
+ def __init__(self, args):
|
|
|
+ Visitor.__init__(self, args)
|
|
|
+ model_name = [arg.split(":", 1)[1] for arg in args if arg.startswith("--modelname:")][0]
|
|
|
+ self.code = "Void function instantiate_%s():\n" % model_name
|
|
|
+ self.free_id = 0
|
|
|
+ self.names = set()
|
|
|
+ self.current_model = None
|
|
|
+ self.current_element = []
|
|
|
+ self.includes = []
|
|
|
+
|
|
|
+ def dump(self):
|
|
|
+ return self.code
|
|
|
+
|
|
|
+ def __getattr__(self, attr):
|
|
|
+ if attr.startswith("visit_"):
|
|
|
+ return empty
|
|
|
+ else:
|
|
|
+ raise AttributeError()
|
|
|
+
|
|
|
+ def visit_start(self, tree):
|
|
|
+ for t in tree.get_tail():
|
|
|
+ self.visit(t)
|
|
|
+
|
|
|
+ def visit_include_files(self, tree):
|
|
|
+ self.includes.append('include %s' % tree.get_children("STRVALUE")[0].get_text())
|
|
|
+
|
|
|
+ def visit_import(self, tree):
|
|
|
+ url = tree.get_children("MV_URL")[0]
|
|
|
+ target = tree.get_children("MODEL_ID")[0]
|
|
|
+ #self.constructors.extend(["import_node", url.get_text(), target.get_text()])
|
|
|
+ self.code += "\timport_node(%s, %s)\n" % (url.get_text(), target.get_text())
|
|
|
+
|
|
|
+ def visit_export(self, tree):
|
|
|
+ url = tree.get_children("MV_URL")[0]
|
|
|
+ target = tree.get_children("MODEL_ID")[0]
|
|
|
+ #self.constructors.extend(["export_node", target.get_text(), url.get_text()])
|
|
|
+ self.code += "\texport_node(%s, %s)\n" % (target.get_text(), url.get_text())
|
|
|
+
|
|
|
+ def visit_model(self, tree):
|
|
|
+ children = tree.get_children("MODEL_ID")
|
|
|
+ model_type = children[0].get_text()
|
|
|
+ model_name = children[-1].get_text()
|
|
|
+ #self.constructors.extend(["instantiate_model", model_type, model_name])
|
|
|
+ self.code += "\tinstantiate_model(%s, %s)\n" % (model_type, model_name)
|
|
|
+ self.current_model = model_name
|
|
|
+ self.names = set()
|
|
|
+ for element in tree.get_children("model_element"):
|
|
|
+ self.visit(element)
|
|
|
+
|
|
|
+ def visit_model_element(self, tree):
|
|
|
+ children = tree.get_children("MODEL_ID")
|
|
|
+ element_type = children[0].get_text()
|
|
|
+ if len(children) == 2 or len(children) == 4:
|
|
|
+ element_name = children[1].get_text()
|
|
|
+ else:
|
|
|
+ element_name = "__%s" % self.free_id
|
|
|
+ self.free_id += 1
|
|
|
+
|
|
|
+ if element_name in self.names:
|
|
|
+ raise Exception("Redefinition of element %s" % element_name)
|
|
|
+
|
|
|
+ if len(children) > 2:
|
|
|
+ # So we have a source and target; but aren't sure which is which, because the name is optional!
|
|
|
+ source_name = children[-2].get_text()
|
|
|
+ target_name = children[-1].get_text()
|
|
|
+ if source_name not in self.names:
|
|
|
+ raise Exception("Source of link %s unknown: %s" % (element_name, source_name))
|
|
|
+ if target_name not in self.names:
|
|
|
+ raise Exception("Target of link %s unknown: %s" % (element_name, target_name))
|
|
|
+
|
|
|
+ #self.constructors.extend(["instantiate_link", self.current_model, element_type, element_name, source_name, target_name])
|
|
|
+ self.code += "\tinstantiate_link(%s, %s, %s, %s, %s)\n" % (self.current_model, element_type, element_name, source_name, target_name)
|
|
|
+ else:
|
|
|
+ #self.constructors.extend(["instantiate_node", self.current_model, element_type, element_name])
|
|
|
+ self.code += "\tinstantiate_node(%s, %s, %s)\n" % (self.current_model, element_type, element_name)
|
|
|
+
|
|
|
+ self.names.add(element_name)
|
|
|
+ self.current_element.append(element_name)
|
|
|
+
|
|
|
+ if tree.get_children("inheritance"):
|
|
|
+ self.visit(tree.get_children("inheritance")[0])
|
|
|
+
|
|
|
+ for attr in tree.get_children("model_attribute"):
|
|
|
+ self.visit(attr)
|
|
|
+
|
|
|
+ self.current_element.pop()
|
|
|
+
|
|
|
+ return element_name
|
|
|
+
|
|
|
+ def visit_inheritance(self, tree):
|
|
|
+ for token in tree.get_children("MODEL_ID"):
|
|
|
+ superclass = token.get_text()
|
|
|
+ if superclass not in self.names:
|
|
|
+ raise Exception("Superclass %s is undefined" % superclass)
|
|
|
+
|
|
|
+ #self.constructors.extend(["instantiate_link", self.current_model, "Inheritance", "%s_inherits_from_%s" % (self.current_element[-1], superclass), self.current_element[-1], superclass])
|
|
|
+ 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)
|
|
|
+ self.names.add("%s_inherits_from_%s" % (self.current_element[-1], superclass))
|
|
|
+
|
|
|
+ def visit_model_attribute(self, tree):
|
|
|
+ children = tree.get_children("MODEL_ID")
|
|
|
+ is_definition = bool(tree.get_children("COLON"))
|
|
|
+ is_assign = bool(tree.get_children("model_attr_instance"))
|
|
|
+ is_nested = bool(tree.get_children("model_element"))
|
|
|
+
|
|
|
+ if is_definition:
|
|
|
+ attr_name = children[0].get_text()
|
|
|
+ attr_optional = len(tree.get_children("OPTIONAL")) > 0
|
|
|
+ attr_type = children[1].get_text()
|
|
|
+ #self.constructors.extend(["model_define_attribute", self.current_model, self.current_element[-1], attr_name, attr_optional, attr_type])
|
|
|
+ self.code += "\tmodel_define_attribute(%s, %s, %s, %s, %s)\n" % (self.current_model, self.current_element[-1], attr_name, attr_optional, attr_type)
|
|
|
+ full_attribute_name = self.current_element[-1] + "_" + attr_name
|
|
|
+
|
|
|
+ if is_assign:
|
|
|
+ # There are also some attributes to set!
|
|
|
+ self.current_element.append(full_attribute_name)
|
|
|
+
|
|
|
+ for f in tree.get_children("model_attr_instance"):
|
|
|
+ self.visit(f)
|
|
|
+
|
|
|
+ self.current_element.pop()
|
|
|
+ elif is_assign:
|
|
|
+ self.visit(tree.get_children("model_attr_instance")[0])
|
|
|
+ elif is_nested:
|
|
|
+ if tree.get_children("MODEL_ID"):
|
|
|
+ contains_link = tree.get_children("MODEL_ID")[0].get_text()
|
|
|
+ else:
|
|
|
+ contains_link = ""
|
|
|
+ entry = self.visit(tree.get_children("model_element")[0])
|
|
|
+ #self.constructors.extend(["instantiate_link", self.current_model, contains_link, "__%s" % self.free_id, self.current_element[-1], entry])
|
|
|
+ self.code += '\tinstantiate_link(%s, %s, "__%s", %s, %s)\n' % (self.current_model, contains_link, self.free_id, self.current_element[-1], entry)
|
|
|
+ self.names.add("__%s" % self.free_id)
|
|
|
+ self.free_id += 1
|
|
|
+
|
|
|
+ def visit_model_attr_instance(self, tree):
|
|
|
+ def constructors_compile(code):
|
|
|
+ code_fragments = code.split("\n")
|
|
|
+ code_fragments = [i for i in code_fragments if i.strip() != ""]
|
|
|
+ code_fragments = [i.replace(" ", "\t") for i in code_fragments]
|
|
|
+ initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments])
|
|
|
+ code_fragments = self.includes + [i[initial_tabs:] for i in code_fragments]
|
|
|
+ code = "\n".join(code_fragments)
|
|
|
+ code += "\n"
|
|
|
+
|
|
|
+ with open(".code.alc", 'w') as f:
|
|
|
+ f.write(code)
|
|
|
+ f.flush()
|
|
|
+ directory = os.path.realpath(__file__).rsplit(os.sep, 1)[0]
|
|
|
+ compiled = do_compile(".code.alc", directory + "/../grammars/actionlanguage.g", "CS")
|
|
|
+ return compiled
|
|
|
+
|
|
|
+ children = tree.get_children("MODEL_ID")
|
|
|
+ attr_name = children[0].get_text()
|
|
|
+ if tree.get_children("value"):
|
|
|
+ # Value attribute
|
|
|
+ attr_value = tree.get_children("value")[0].get_tail()[0]
|
|
|
+ if attr_value.head == "STRVALUE":
|
|
|
+ attr_value = attr_value.get_text()[1:-1]
|
|
|
+ elif attr_value.head == "TRUE":
|
|
|
+ attr_value = True
|
|
|
+ elif attr_value.head == "FALSE":
|
|
|
+ attr_value = False
|
|
|
+ elif attr_value.head == "DEC_NUMBER":
|
|
|
+ attr_value = int(attr_value.get_text())
|
|
|
+ elif attr_value.head == "FLOAT_NUMBER":
|
|
|
+ attr_value = float(attr_value.get_text())
|
|
|
+ else:
|
|
|
+ raise Exception(attr_value.head)
|
|
|
+ #self.constructors.extend(["instantiate_attribute", self.current_model, self.current_element[-1], attr_name, attr_value])
|
|
|
+ self.code += "\tinstantiate_attribute(%s, %s, %s, %s)\n" % (self.current_model, self.current_element[-1], attr_name, attr_value)
|
|
|
+ elif tree.get_children("DOLLAR"):
|
|
|
+ # Coded attribute
|
|
|
+ #self.constructors.extend(["instantiate_attribute_code", self.current_model, self.current_element[-1], attr_name])
|
|
|
+ #self.constructors.extend(constructors_compile(tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()))
|
|
|
+ code = tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()
|
|
|
+
|
|
|
+ code_fragments = code.split("\n")
|
|
|
+ code_fragments = [i for i in code_fragments if i.strip() != ""]
|
|
|
+ code_fragments = [i.replace(" ", "\t") for i in code_fragments]
|
|
|
+ initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments])
|
|
|
+ code_fragments = [i[initial_tabs:] for i in code_fragments]
|
|
|
+ code_fragments.append("")
|
|
|
+ code = "\n".join(code_fragments)
|
|
|
+
|
|
|
+ func_name = "__code__%s" % abs(hash(code))
|
|
|
+ self.code += "\tinstantiate_attribute_code(%s, %s, %s, %s)\n" % (self.current_model, self.current_element[-1], attr_name, func_name)
|
|
|
+
|
|
|
+ # Rewrite the name of the function to func_name
|
|
|
+ prepend = code
|
|
|
+ before, after = prepend.split("function ", 1)
|
|
|
+ before = before + "function "
|
|
|
+ after = "(" + after.split("(", 1)[1]
|
|
|
+ prepend = before + func_name + after
|
|
|
+
|
|
|
+ # And prepend the actual code block
|
|
|
+ self.code = prepend + self.code
|