Kaynağa Gözat

Patched change in model_types semantics

Yentl Van Tendeloo 7 yıl önce
ebeveyn
işleme
9593768dcf

+ 18 - 1
bootstrap/semi_primitives.alc

@@ -420,7 +420,7 @@ String function reverseKeyLookup(dict : Element, element : Element):
 	
 	return ""!
 
-Element function reverseKeyLookupMulti(dict : Element, element : Element):
+Element function reverseKeyLookupMultiValue(dict : Element, element : Element):
 	Integer nr_out
 	Integer counter
 	Element link
@@ -437,6 +437,23 @@ Element function reverseKeyLookupMulti(dict : Element, element : Element):
 	
 	return result!
 
+Element function reverseKeyLookupMultiID(dict : Element, element : Element):
+	Integer nr_out
+	Integer counter
+	Element link
+	Element result
+
+	result = set_create()
+	nr_out = read_nr_out(dict)
+	counter = 0
+	while (counter < nr_out):
+		if (element_eq(read_edge_dst(read_out(dict, counter)), element)):
+			// Got a match
+			set_add(result, read_edge_dst(read_out(read_out(dict, counter), 0)))
+		counter = counter + 1
+	
+	return result!
+
 Boolean function list_in(list : Element, elem : Element):
 	Integer i
 	i = 0

+ 31 - 10
bootstrap/typing.alc

@@ -11,6 +11,8 @@ Element function get_type_mapping(model : Element):
 	Element edge
 	Element keys
 	String key
+	String m_name
+	String mm_name
 
 	keys = dict_keys(model["type_mapping"])
 
@@ -20,9 +22,11 @@ Element function get_type_mapping(model : Element):
 		mm = model["metamodel"]["model"][model["type_mapping"][key]]
 		edge = create_edge(m, mm)
 
-		dict_add_fast(tm_model, cast_id(m), m)
-		if (bool_not(dict_in(tm_model, cast_id(mm)))):
-			dict_add_fast(tm_model, cast_id(mm), mm)
+		m_name = "instance_" + key
+		mm_name = "type_" + cast_string(model["type_mapping"][key])
+		dict_add_fast(tm_model, m_name, m)
+		if (bool_not(dict_in(tm_model, mm_name))):
+			dict_add_fast(tm_model, mm_name, mm)
 		dict_add_fast(tm_model, cast_id(edge), edge)
 
 	return tm_model!
@@ -30,24 +34,41 @@ Element function get_type_mapping(model : Element):
 Void function set_type_mapping(model : Element, type_mapping_model : Element):
 	// Serialize model to dictionary
 	Element type_mapping
-	Element rev_model
-	Element rev_metamodel
 	Element keys
 	String key
+	String source_name
+	String destination_name
+	String tmp_source_name
+	String tmp_destination_name
+	Element lookups
 
 	type_mapping = dict_create()
 	keys = dict_keys(type_mapping_model)
-	rev_model = make_reverse_dictionary(model["model"])
-	rev_metamodel = make_reverse_dictionary(model["metamodel"]["model"])
 
 	while (set_len(keys) > 0):
 		key = set_pop(keys)
 		if (is_edge(type_mapping_model[key])):
-			if (bool_not(bool_or(dict_in(rev_model, cast_id(type_mapping_model[key])), dict_in(rev_metamodel, cast_id(type_mapping_model[key]))))):
+			lookups = reverseKeyLookupMultiID(type_mapping_model, read_edge_src(type_mapping_model[key]))
+			source_name = ""
+			while (set_len(lookups) > 0):
+				tmp_source_name = set_pop(lookups)
+				if (string_startswith(tmp_source_name, "instance_")):
+					source_name = string_replace(tmp_source_name, "instance_", "")
+					break!
+
+			lookups = reverseKeyLookupMultiID(type_mapping_model, read_edge_dst(type_mapping_model[key]))
+			destination_name = ""
+			while (set_len(lookups) > 0):
+				tmp_destination_name = set_pop(lookups)
+				if (string_startswith(tmp_destination_name, "type_")):
+					destination_name = string_replace(tmp_destination_name, "type_", "")
+					break!
+
+			if (bool_and(dict_in(model["model"], source_name), dict_in(model["metamodel"]["model"], destination_name))):
 				// Element is in neither model or metamodel
 				// Must be a typing link!
 				// So add it
-				dict_add_fast(type_mapping, rev_model[cast_id(read_edge_src(type_mapping_model[key]))], rev_metamodel[cast_id(read_edge_dst(type_mapping_model[key]))])
+				dict_add_fast(type_mapping, source_name, destination_name)
 
 	dict_overwrite(model, "type_mapping", type_mapping)
 	return!
@@ -58,7 +79,7 @@ Element function elements_typed_by(model : Element, type_name : String):
 	String temp
 
 	result = set_create()
-	temp_result = reverseKeyLookupMulti(get_type_mapping_as_dict(model), type_name)
+	temp_result = reverseKeyLookupMultiValue(get_type_mapping_as_dict(model), type_name)
 	while (set_len(temp_result) > 0):
 		temp = set_pop(temp_result)
 		if (dict_in(model["model"], temp)):

+ 1 - 1
examples/multi_conformance.py

@@ -52,7 +52,7 @@ model_add("formalisms/simple_mm", "formalisms/SimpleClassDiagrams", mm)
 model_add("models/model_string", "formalisms/simple_mm", model_string)
 model_add("models/model_integer", "formalisms/simple_mm", model_integer)
 
-transformation_add_AL({"model": "formalisms/simple_mm", "metamodel": "formalisms/SimpleClassDiagrams", "type_mapping": "formalisms/TypeMapping"}, {}, "models/conformance_AToMPM", open("models/Conformance/AToMPM.alc", 'r').read())
+transformation_add_AL({"model": "formalisms/Bottom", "metamodel": "formalisms/SimpleClassDiagrams", "type_mapping": "formalisms/TypeMapping"}, {}, "models/conformance_AToMPM", open("models/Conformance/AToMPM.alc", 'r').read())
 #transformation_add_AL({"model": "formalisms/simple_mm", "metamodel": "formalisms/SimpleClassDiagrams", "type_mapping": "formalisms/TypeMapping"}, {}, "models/conformance_MetaDepth", open("models/Conformance/MetaDepth.alc", 'r').read())
 
 print(model_types("models/model_string"))

+ 2 - 1
interface/HUTN/includes/primitives.alh

@@ -116,7 +116,8 @@ Element function set_create()
 Element function list_create()
 Element function dict_create()
 String function reverseKeyLookup(a: Element, b: Element)
-Element function reverseKeyLookupMulti(a: Element, b: Element)
+Element function reverseKeyLookupMultiValue(a: Element, b: Element)
+Element function reverseKeyLookupMultiID(a: Element, b: Element)
 Element function dict_values(dict : Element)
 Boolean function is_error(a : Element)
 Element function range(max : Integer)

+ 19 - 1
kernel/modelverse_kernel/compiled.py

@@ -50,7 +50,25 @@ def get_superclasses(a, b, **remainder):
 
     yield [("RETURN", [{'id': result}])]
 
-def reverseKeyLookupMulti(a, b, **remainder):
+def reverseKeyLookupMultiID(a, b, **remainder):
+    edges, result = yield [("RO", [a['id']]), ("CN", [])]
+    expanded_edges = yield [("RE", [i]) for i in edges]
+    values = [i[1] for i in expanded_edges]
+
+    # Keep results in a local Python set, as we want to bundle as many requests as possible
+    todo = set()
+    for i, edge in enumerate(values):
+        if b['id'] == edge:
+            todo.add(i)
+
+    outgoings = yield [("RO", [edges[i]]) for i in todo]
+    values = yield [("RE", [outgoing[0]]) for outgoing in outgoings]
+    edges = yield [("CE", [result, result]) for value in values]
+    yield [("CE", [edge, value[1]]) for edge, value in zip(edges, values)]
+
+    yield [("RETURN", [{'id': result}])]
+
+def reverseKeyLookupMultiValue(a, b, **remainder):
     if "value" not in b:
         b['value'], = yield [("RV", [b['id']])]
 

+ 6 - 0
models/Conformance/AToMPM.alc

@@ -27,10 +27,16 @@ Boolean function main(model : Element):
 	// TODO other option: make the type mapping refer to names/IDs instead of identifiers, although this is problematic in case we connect to ourselves (self-conformance!)
 	Element links
 	String link
+	Element type_mapping
+	type_mapping = dict_create()
+
 	links = allInstances(model, "type_mapping/TypeLink")
 	while (set_len(links) > 0):
 		link = set_pop(links)
 		log("Association connects: " + readAssociationSource(model, link) + " --> " + readAssociationDestination(model, link))
+		dict_add(type_mapping, "model/" + string_replace(readAssociationSource(model, link), "type_mapping/instance_", ""), "metamodel/" + string_replace(readAssociationDestination(model, link), "type_mapping/type_", ""))
+	
+	log("Found type mapping: " + dict_to_string(type_mapping))
 
 	String class
 	Element instances

+ 2 - 2
wrappers/classes/modelverse.xml

@@ -435,7 +435,7 @@
 
                             <transition cond="self.expect_response_partial('Success: ')" target="../send_metadata">
                                 <script>
-                                    self.registered_metamodel[self.parameters[0]] = set(self.split_response(self.responses.pop(0))).pop()
+                                    self.registered_metamodel[self.parameters[0]] = set(self.split_response(self.responses.pop(0))).pop().split(", ")[0]
                                 </script>
                             </transition>
                         </state>
@@ -2012,7 +2012,7 @@
 
                         <transition cond="self.expect_response_partial('Success: ')" target="../OK">
                             <script>
-                                self.registered_metamodel[self.current_model] = set(self.split_response(self.responses.pop(0))).pop()
+                                self.registered_metamodel[self.current_model] = set(self.split_response(self.responses.pop(0))).pop().split(", ")[0]
                             </script>
                         </transition>
                     </state>

+ 3 - 3
wrappers/modelverse_SCCD.py

@@ -1,7 +1,7 @@
 """
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
-Date:   Thu May 24 17:42:24 2018
+Date:   Fri May 25 10:59:57 2018
 
 Model author: Yentl Van Tendeloo
 Model name:   MvK Server
@@ -2598,7 +2598,7 @@ class Modelverse(RuntimeClassBase):
         return self.parameters[0] not in self.registered_metamodel
     
     def _initialized_behaviour_operations_model_overwrite_search_0_exec(self, parameters):
-        self.registered_metamodel[self.parameters[0]] = set(self.split_response(self.responses.pop(0))).pop()
+        self.registered_metamodel[self.parameters[0]] = set(self.split_response(self.responses.pop(0))).pop().split(", ")[0]
     
     def _initialized_behaviour_operations_model_overwrite_search_0_guard(self, parameters):
         return self.expect_response_partial('Success: ')
@@ -3357,7 +3357,7 @@ class Modelverse(RuntimeClassBase):
         return self.current_model not in self.registered_metamodel
     
     def _initialized_behaviour_going_manual_search_0_exec(self, parameters):
-        self.registered_metamodel[self.current_model] = set(self.split_response(self.responses.pop(0))).pop()
+        self.registered_metamodel[self.current_model] = set(self.split_response(self.responses.pop(0))).pop().split(", ")[0]
     
     def _initialized_behaviour_going_manual_search_0_guard(self, parameters):
         return self.expect_response_partial('Success: ')