Переглянути джерело

First step towards compiling models in the bootstrap file as well

Yentl Van Tendeloo 8 роки тому
батько
коміт
2b15a6871c

+ 34 - 4
bootstrap/bootstrap.py

@@ -8,9 +8,8 @@ def bootstrap():
     root = ["__hierarchy"]
 
     task_manager = "task_manager"
-    initial_code_manager = "bootstrap/initial_code_manager.alb"
-    initial_code_task = "bootstrap/initial_code_task.alb"
-    bootstrap_files = glob.glob("bootstrap/*.alc") + [initial_code_manager, initial_code_task]
+    initial_code_manager = "bootstrap/initial_code_manager.alc"
+    initial_code_task = "bootstrap/initial_code_task.alc"
 
     task_data = [   "input",
                     "output",
@@ -201,11 +200,42 @@ def bootstrap():
                 f.write("Node __objects()\n", both=False)
                 f.write('Dict (__hierarchy, "objects", __objects)\n', both=False)
 
+                def compile_code_MO(filename, model_name)
+                    import sys
+                    sys.path.append("interface/HUTN/")
+                    from hutn_compiler.compiler import main as compile_code
+                    model_constructors = compile_code(filename, "interface/HUTN/grammars/modelling.g", "MB", ["--modelname:%s" % model_name])
+                    print("Got model construction code: " + str(model_constructors))
+
+                # Compile all model definitions to ALC directly
+                total_alc = ""
+                binding_alc = 'Void initialize_MMs():\n\tinitialize_SCD("models/SimpleClassDiagrams")\n'
+
+                bootstrap_models = glob.glob("bootstrap/*.mvc")
+                for bootstrap_model in bootstrap_models:
+                    # Compile the subfile
+                    bootstrap_model = bootstrap_model.replace("\\", "/")
+                    model_name = bootstrap_model.rsplit(".mvc", 1)[0].rsplit("/", 1)[1]
+                    print("[MVC] %s" % bootstrap_name)
+                    alc = compile_code_MO(bootstrap_model, model_name)
+                    print("ALC: " + str(alc))
+                    total_alc += alc
+                    binding_alc += "\tinitialize_%s()\n" % model_name
+
+                # Write out the ALC to a new .metamodels.alc
+                binding_alc += "\treturn!\n"
+                new_metamodels_alc = open("bootstrap/metamodels.alt", 'r').read() + total_alc + binding_alc
+
+                # Now overwrite the .metamodels.alc file
+                with open("bootstrap/.metamodels.alc", "w") as mm:
+                    mm.write(new_metamodels_alc)
+
                 # Compile all files and add to structure manually
+                bootstrap_files = glob.glob("bootstrap/*.alc")
                 for bootstrap_file in bootstrap_files:
                     # Compile the subfile
                     bootstrap_file = bootstrap_file.replace("\\", "/")
-                    print("[COMP] %s" % bootstrap_file)
+                    print("[ALC] %s" % bootstrap_file)
                     symbols = {}
                     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)
 

core/core_algorithm.alc → bootstrap/core_algorithm.alc


core/core_formalism.mvc → bootstrap/core_formalism.mvc


bootstrap/initial_code_manager.alb → bootstrap/initial_code_manager.alc


bootstrap/initial_code_task.alb → bootstrap/initial_code_task.alc


bootstrap/metamodels.alc → bootstrap/metamodels.alt


core/mini_modify.alc → bootstrap/mini_modify.alc


core/pm.mvc → bootstrap/pm.mvc


+ 1 - 1
bootstrap/task_manager.alc

@@ -10,7 +10,7 @@ Void function task_management():
 	Element input_value
 
 	// Initialize the basic formalisms before allowing new users
-	initialize_SCD("models/SimpleClassDiagrams")
+	initialize_MMs()
 	
 	while (True):
 		taskname = input()

core/tracability.mvc → bootstrap/tracability.mvc


+ 2 - 0
interface/HUTN/hutn_compiler/compiler.py

@@ -144,6 +144,7 @@ def main(input_file, grammar_file, mode, args=[], symbols=None):
     from constructors_visitor import ConstructorsVisitor
     from constructors_object_visitor import ConstructorsObjectVisitor
     from model_visitor import ModelVisitor
+    from model_bootstrap_visitor import ModelBootstrapVisitor
     from model_object_visitor import ModelObjectVisitor
 
     modes = {
@@ -157,6 +158,7 @@ def main(input_file, grammar_file, mode, args=[], symbols=None):
         "CS" : [SemanticsVisitor, ConstructorsVisitor],
         "CO" : [SemanticsVisitor, ConstructorsObjectVisitor],
         "M" : [ModelVisitor],
+        "MB" : [ModelBootstrapVisitor],
         "MO" : [ModelObjectVisitor],
     }
     try:

+ 205 - 0
interface/HUTN/hutn_compiler/model_bootstrap_visitor.py

@@ -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

core/mini_modify.alh → interface/HUTN/includes/mini_modify.alh