浏览代码

Fixes to compiler which ignored inheritance links

Yentl Van Tendeloo 8 年之前
父节点
当前提交
e37ff517d7

二进制
bootstrap/bootstrap.m.gz


+ 3 - 6
bootstrap/modelling.alc

@@ -244,9 +244,7 @@ String function instantiate_link(model : Element, type : String, name : String,
 		Element in
 		Element options
 
-		out = selectPossibleOutgoing(model, source, create_node())
-		in = selectPossibleIncoming(model, destination, create_node())
-		options = set_overlap(out, in)
+		options = allowedAssociationsBetween(model, source, destination)
 
 		if (read_nr_out(options) == 1):
 			type = set_pop(options)
@@ -476,6 +474,8 @@ Void function construct_model():
 			instantiate_attribute(global_models[input()], input(), input(), input())
 		elif (command == "instantiate_attribute_ref"):
 			instantiate_attribute_ref(global_models[input()], input(), input(), input())
+		elif (command == "instantiate_attribute_code"):
+			instantiate_attribute_code(global_models[input()], input(), input(), input())
 		elif (command == "instantiate_link"):
 			instantiate_link(global_models[input()], input(), input(), input(), input())
 		elif (command == "define_inheritance"):
@@ -491,9 +491,6 @@ Void function construct_model():
 			String location
 			local_name = input()
 			location = input()
-			log("Exporting to location " + location)
-			log("  name: " + local_name)
-			log("Export element: " + cast_e2s(global_models[local_name]))
 			export_node(location, global_models[local_name])
 		elif (command == "import_node"):
 			Element m

+ 41 - 0
bootstrap/object_operations.alc

@@ -202,3 +202,44 @@ Element function allAssociationDestinations(model : Element, name : String, asso
 		set_add(result, readAssociationDestination(model, set_pop(tmp)))
 
 	return result!
+
+Element function allowedAssociationsBetween(model : Element, src : String, dst : String):
+	// Go to the type and find all possibilities
+	String type
+	Element all_types
+	Integer nr_edges
+	Integer i
+	Element result
+	Element edge
+	String edge_name
+	String dst_name
+
+	result = create_node()
+	type = reverseKeyLookup(model["metamodel"]["model"], dict_read_node(model["type_mapping"], model["model"][src]))
+	log("Computing all types")
+	all_types = get_superclasses(model["metamodel"], type)
+	log("Got types: " + set_to_string(all_types))
+
+	while (read_nr_out(all_types) > 0):
+		type = set_pop(all_types)
+		nr_edges = read_nr_out(model["metamodel"]["model"][type])
+		i = 0
+		while (i < nr_edges):
+			edge = read_out(model["metamodel"]["model"][type], i)
+
+			if (set_in(model["metamodel"]["model"], edge)):
+				// Find destination
+				dst_name = reverseKeyLookup(model["metamodel"]["model"], read_edge_dst(edge))
+				edge_name = reverseKeyLookup(model["metamodel"]["model"], edge)
+				log("Got destination: " + log(dst_name))
+				log("  with name: " + edge_name)
+				log("Is instance: " + dst)
+
+				if (is_nominal_instance(model, dst, dst_name)):
+					// Find out whether our dst is an instance of the found destination type
+					log("Adding edge: " + edge_name)
+					set_add(result, edge_name)
+
+			i = i + 1
+
+	return result!

+ 23 - 23
integration/test_pn_interface.py

@@ -677,7 +677,7 @@ Void function action(host_model : Element, name : String, mapping : Element):
         constructor_unmark_place_action = get_constructor(code_unmark_place_action)
 
         self.assertTrue(run_file(all_files,
-            ["new", "SimpleClassDiagrams", "PetriNets_runtime",
+            ["new", "SimpleClassDiagrams", "PetriNets_Runtime",
                 "set_inheritance", "Inheritance",
                 "instantiate", "Class", "Natural",
                 "instantiate", "Class", "Boolean",
@@ -691,7 +691,7 @@ Void function action(host_model : Element, name : String, mapping : Element):
                 "instantiate", "Association", "T2P", "Transition", "Place",
                 "attr_def", "T2P", "weight", "Natural",
                 "exit",
-             "new", "PetriNets_runtime", "pn",
+             "new", "PetriNets_Runtime", "pn",
                 "instantiate", "Place", "p1",
                 "attr_add", "p1", "tokens", 1,
                 "attr_add", "p1", "executed", False,
@@ -705,8 +705,8 @@ Void function action(host_model : Element, name : String, mapping : Element):
                 "instantiate", "P2T", "p2t2", "p2", "t1",
                 "attr_add", "p2t2", "weight", 1,
                 "exit",
-             "ramify", "PetriNets_runtime",
-             "new", "PetriNets_runtime_SCHEDULE", "pn_simulate",
+             "ramify", "PetriNets_Runtime",
+             "new", "PetriNets_Runtime_SCHEDULE", "pn_simulate",
                 # Rule 1: mark transition to execute
                 # LHS
                 "instantiate", "LHS", "lhs_mark",
@@ -916,13 +916,13 @@ Void function action(host_model : Element, name : String, mapping : Element):
 
         schedule_model = \
             """
-            import models/PetriNets_Runtime_Schedule as PN_Transform
+            import models/PetriNets_Runtime_SCHEDULE as PN_Transform
 
             PN_Transform s {
                 Composite schedule {
-                    Failure failure {}
-                    Success success {}
-                    Atomic mark {
+                    {Contains} Failure failure {}
+                    {Contains} Success success {}
+                    {Contains} Atomic mark {
                         LHS {
                             Pre_Transition {
                                 label = "1"
@@ -958,7 +958,7 @@ Void function action(host_model : Element, name : String, mapping : Element):
                             }
                         }
                     }
-                    Atomic consume {
+                    {Contains} Atomic consume {
                         LHS {
                             Pre_Transition {
                                 label = "0"
@@ -1010,7 +1010,7 @@ Void function action(host_model : Element, name : String, mapping : Element):
                             }
                         }
                     }
-                    Atomic produce {
+                    {Contains} Atomic produce {
                         LHS {
                             Pre_Transition {
                                 label = "0"
@@ -1062,7 +1062,7 @@ Void function action(host_model : Element, name : String, mapping : Element):
                             }
                         }
                     }
-                    Atomic unmark_transition {
+                    {Contains} Atomic unmark_transition {
                         LHS {
                             Pre_Transition {
                                 label = "0"
@@ -1089,7 +1089,7 @@ Void function action(host_model : Element, name : String, mapping : Element):
                             }
                         }
                     }
-                    Atomic unmark_place {
+                    {Contains} Atomic unmark_place {
                         LHS {
                             Pre_Place {
                                 label = "0"
@@ -1116,16 +1116,16 @@ Void function action(host_model : Element, name : String, mapping : Element):
                             }
                         }
                     }
-                    OnSuccess (mark, consume) {}
-                    OnFailure (mark, failure) {}
-                    OnSuccess (consume, consume) {}
-                    OnFailure (consume, produce) {}
-                    OnSuccess (produce, produce) {}
-                    OnFailure (produce, unmark_transition) {}
-                    OnSuccess (unmark_transition, unmark_place) {}
-                    OnFailure (unmark_transition, failure) {}
-                    OnSuccess (unmark_place, unmark_place) {}
-                    OnFailure (unmark_place, success) {}
+                    {Contains} OnSuccess (mark, consume) {}
+                    {Contains} OnFailure (mark, failure) {}
+                    {Contains} OnSuccess (consume, consume) {}
+                    {Contains} OnFailure (consume, produce) {}
+                    {Contains} OnSuccess (produce, produce) {}
+                    {Contains} OnFailure (produce, unmark_transition) {}
+                    {Contains} OnSuccess (unmark_transition, unmark_place) {}
+                    {Contains} OnFailure (unmark_transition, failure) {}
+                    {Contains} OnSuccess (unmark_place, unmark_place) {}
+                    {Contains} OnFailure (unmark_place, success) {}
                     initial = !mark
                 }
             }
@@ -1136,7 +1136,7 @@ Void function action(host_model : Element, name : String, mapping : Element):
         self.assertTrue(run_file(all_files,
             get_model_constructor(PN_runtime) + \
                 get_model_constructor(PN_model) + [
-                "ramify", "PetriNets_runtime",
+                "ramify", "PetriNets_Runtime",
                 ] + get_model_constructor(schedule_model) + [
                 "transform", "pn", "pn_simulate",
                 "load", "pn",

+ 22 - 14
interface/HUTN/hutn_compiler/model_visitor.py

@@ -12,7 +12,7 @@ class ModelVisitor(Visitor):
         self.free_id = 0
         self.name_maps = {}
         self.current_model = None
-        self.current_element = None
+        self.current_element = []
         self.includes = []
 
     def dump(self):
@@ -46,8 +46,12 @@ class ModelVisitor(Visitor):
         model_type = children[0].get_text()
         model_name = children[-1].get_text()
         self.constructors.extend(["instantiate_model", model_type, model_name])
-        if "LPAR" in tree.get_tail():
+        print("CHECK for inheritance")
+        if tree.get_children("LPAR"):
+            print("ADD")
             self.constructors.extend(["define_inheritance", model_name, tree.get_children("MODEL_ID")[1].get_text()])
+        else:
+            print("NO!")
         self.current_model = model_name
         for element in tree.get_children("model_element"):
             self.visit(element)
@@ -68,7 +72,8 @@ class ModelVisitor(Visitor):
             self.constructors.extend(["instantiate_link", 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.current_element = element_name
+
+        self.current_element.append(element_name)
 
         if tree.get_children("inheritance"):
             self.visit(tree.get_children("inheritance")[0])
@@ -76,12 +81,14 @@ class ModelVisitor(Visitor):
         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()
-            self.constructors.extend(["instantiate_link", self.current_model, "Inheritance", "%s_inherits_from_%s" % (self.current_element, superclass), self.current_element, superclass])
+            self.constructors.extend(["instantiate_link", self.current_model, "Inheritance", "%s_inherits_from_%s" % (self.current_element[-1], superclass), self.current_element[-1], superclass])
 
     def visit_model_attribute(self, tree):
         children = tree.get_children("MODEL_ID")
@@ -93,16 +100,17 @@ class ModelVisitor(Visitor):
         if is_definition:
             attr_name = children[0].get_text()
             attr_type = children[1].get_text()
-            self.constructors.extend(["instantiate_link", self.current_model, "Association", self.current_element + "_" + attr_name, self.current_element, attr_type])
-            full_attribute_name = self.current_element + "_" + attr_name
+            self.constructors.extend(["instantiate_link", self.current_model, "Association", self.current_element[-1] + "_" + attr_name, self.current_element[-1], attr_type])
+            full_attribute_name = self.current_element[-1] + "_" + attr_name
             self.constructors.extend(["instantiate_attribute", self.current_model, full_attribute_name, "name", attr_name])
             if is_assign:
                 # There are also some attributes to set!
-                old_element = self.current_element
-                self.current_element = full_attribute_name
+                self.current_element.append(full_attribute_name)
+
                 for f in tree.get_children("model_attr_instance"):
                     self.visit(f)
-                self.current_element = old_element
+
+                self.current_element.pop()
         elif is_assign:
             self.visit(tree.get_children("model_attr_instance")[0])
         elif is_constraint:
@@ -119,14 +127,14 @@ class ModelVisitor(Visitor):
                 f.flush()
             directory = os.path.realpath(__file__).rsplit(os.sep, 1)[0]
             compiled = do_compile(".constraint.alc", directory + "/../grammars/actionlanguage.g", "CS")
-            self.constructors.extend(["add_constraint", self.current_model, self.current_element] + compiled)
+            self.constructors.extend(["add_constraint", self.current_model, self.current_element[-1]] + compiled)
         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, entry])
+            self.constructors.extend(["instantiate_link", self.current_model, contains_link, "__%s" % self.free_id, self.current_element[-1], entry])
             self.free_id += 1
 
     def visit_model_attr_instance(self, tree):
@@ -163,11 +171,11 @@ class ModelVisitor(Visitor):
                 attr_value = float(attr_value.get_text())
             else:
                 raise Exception(attr_value.head)
-            self.constructors.extend(["instantiate_attribute", self.current_model, self.current_element, attr_name, attr_value])
+            self.constructors.extend(["instantiate_attribute", 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, attr_name])
+            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()))
         else:
             # Assign direct reference
-            self.constructors.extend(["instantiate_attribute_ref", self.current_model, self.current_element, attr_name, tree.get_children("MODEL_ID")[1].get_text()])
+            self.constructors.extend(["instantiate_attribute_ref", self.current_model, self.current_element[-1], attr_name, tree.get_children("MODEL_ID")[1].get_text()])

+ 1 - 0
interface/HUTN/includes/object_operations.alh

@@ -11,3 +11,4 @@ String function readAssociationSource(model : Element, name : String)
 String function readAssociationDestination(model : Element, name : String)
 String function followAssociation(model : Element, element_name : String, association_name : String)
 Element function allAssociationDestinations(model : Element, name : String, association_type : String)
+Element function allowedAssociationsBetween(model : Element, src : String, dst : String)

+ 7 - 0
kernel/modelverse_kernel/compiled.py

@@ -299,8 +299,15 @@ def get_superclasses(a, b, **remainder):
 
     result, =        yield [("CN", [])]
     worklist = [subclass]
+
+    touched = set()
+
     while worklist:
         subclass = worklist.pop()
+        if subclass in touched:
+            raise Exception("Loop in Inheritance links")
+        else:
+            touched.add(subclass)
         res = elem_to_name[subclass]
         yield [("CE", [result, res])]