Browse Source

Working conformance check for AToMPM (multi-inheritance part)

Yentl Van Tendeloo 7 years ago
parent
commit
57b95d3ebb

+ 1 - 0
bootstrap/bootstrap.py

@@ -76,6 +76,7 @@ def bootstrap():
                     "element_eq": ["Boolean", "Element", "Element"],
                     "element_eq": ["Boolean", "Element", "Element"],
                     "read_root": ["Element"],
                     "read_root": ["Element"],
                     "read_taskroot": ["Element"],
                     "read_taskroot": ["Element"],
+                    "list_sort": ["Element", "Element"],
                     "log": ["String", "String"],
                     "log": ["String", "String"],
                     "time": ["Float"],
                     "time": ["Float"],
                     "hash": ["String", "String"],
                     "hash": ["String", "String"],

+ 1 - 17
bootstrap/conformance_finding.alc

@@ -32,11 +32,6 @@ Boolean function find_type_mapping(model : Element):
 	// 2) find a mapping based on the current partial mapping, but only if it is not yet complete
 	// 2) find a mapping based on the current partial mapping, but only if it is not yet complete
 	// TODO this must be expanded for other things than trivial metamodels!
 	// TODO this must be expanded for other things than trivial metamodels!
 	if (dict_len(model["model"]) > dict_len(tm)):
 	if (dict_len(model["model"]) > dict_len(tm)):
-		log("Model is incompletely typed!")
-		log("Model has: " + set_to_string(dict_keys(model["model"])))
-		log("Type mapping has: " + set_to_string(dict_keys(tm)))
-		log("Difference: " + set_to_string(set_difference(dict_keys(model["model"]), dict_keys(tm))))
-
 		// TODO for now, this only returns something for a simple case, where the MM has one edge, and one node
 		// TODO for now, this only returns something for a simple case, where the MM has one edge, and one node
 		//      and it makes the assumption that SCD is the M3 level...
 		//      and it makes the assumption that SCD is the M3 level...
 
 
@@ -53,14 +48,11 @@ Boolean function find_type_mapping(model : Element):
 		nodes = allInstances(model["metamodel"], "Class")
 		nodes = allInstances(model["metamodel"], "Class")
 		edges = allInstances(model["metamodel"], "Association")
 		edges = allInstances(model["metamodel"], "Association")
 
 
-		log("Searching for type...")
 		if (bool_and(set_len(edges) == 1, set_len(nodes) == 1)):
 		if (bool_and(set_len(edges) == 1, set_len(nodes) == 1)):
 			// Simple allocation: this seems like conformance bottom
 			// Simple allocation: this seems like conformance bottom
 			node_source_element = set_pop(nodes)
 			node_source_element = set_pop(nodes)
 			node_target_element = node_source_element
 			node_target_element = node_source_element
 			edge_element = set_pop(edges)
 			edge_element = set_pop(edges)
-			log("Found node: " + node_source_element)
-			log("Found edge: " + edge_element)
 
 
 		elif (bool_and(set_len(edges) == 1, set_len(nodes) == 2)):
 		elif (bool_and(set_len(edges) == 1, set_len(nodes) == 2)):
 			// Simple allocation: this seems like a type mapping
 			// Simple allocation: this seems like a type mapping
@@ -70,13 +62,9 @@ Boolean function find_type_mapping(model : Element):
 			node_target_element = readAssociationDestination(model["metamodel"], edge_element)
 			node_target_element = readAssociationDestination(model["metamodel"], edge_element)
 
 
 			if (value_eq(node_source_element, node_target_element)):
 			if (value_eq(node_source_element, node_target_element)):
-				log("Source and target are the same, meaning that the second node is unknown")
+				log("Could not automatically deduce mapping in a trivial way!")
 				return False!
 				return False!
 
 
-			log("Found edge: " + edge_element)
-			log("Found source node: " + node_source_element)
-			log("Found target node: " + node_target_element)
-
 		else:
 		else:
 			log("Could not automatically deduce mapping in a trivial way!")
 			log("Could not automatically deduce mapping in a trivial way!")
 			return False!
 			return False!
@@ -84,7 +72,6 @@ Boolean function find_type_mapping(model : Element):
 
 
 		// Now we have both an edge_element and node_element of the metamodel
 		// Now we have both an edge_element and node_element of the metamodel
 		// Now just trivially bind all elements!
 		// Now just trivially bind all elements!
-		log("Searching for type...")
 		elems = dict_keys(model["model"])
 		elems = dict_keys(model["model"])
 		while (set_len(elems) > 0):
 		while (set_len(elems) > 0):
 			elem = set_pop(elems)
 			elem = set_pop(elems)
@@ -92,13 +79,10 @@ Boolean function find_type_mapping(model : Element):
 			if (bool_and(is_edge(model["model"][elem]), read_nr_out(model["model"][elem]) == 0)):
 			if (bool_and(is_edge(model["model"][elem]), read_nr_out(model["model"][elem]) == 0)):
 				// An edge, and there is always exactly one, so type
 				// An edge, and there is always exactly one, so type
 				retype(model, elem, edge_element)
 				retype(model, elem, edge_element)
-				log("Type " + elem + " as " + edge_element)
 
 
 				// The source and target are ALWAYS typed as well!
 				// The source and target are ALWAYS typed as well!
 				retype(model, readAssociationSource(model, elem), node_source_element)
 				retype(model, readAssociationSource(model, elem), node_source_element)
-				log("Type " + readAssociationSource(model, elem) + " as " + node_source_element)
 				retype(model, readAssociationDestination(model, elem), node_target_element)
 				retype(model, readAssociationDestination(model, elem), node_target_element)
-				log("Type " + readAssociationDestination(model, elem) + " as " + node_target_element)
 			elif (node_source_element == node_target_element):
 			elif (node_source_element == node_target_element):
 				// A node, and we are sure that there is only one
 				// A node, and we are sure that there is only one
 				retype(model, elem, node_source_element)
 				retype(model, elem, node_source_element)

+ 3 - 3
bootstrap/core_algorithm.alc

@@ -80,9 +80,9 @@ String function get_instanceOf_link(model_id : String, metamodel_id : String):
 	if (set_len(all_links) > 1):
 	if (set_len(all_links) > 1):
 		log("WARNING: multiple instanceOf relations were detected for this model; picking one at random!")
 		log("WARNING: multiple instanceOf relations were detected for this model; picking one at random!")
 	elif (set_len(all_links) == 0):
 	elif (set_len(all_links) == 0):
-		log("No types found!")
-		log("Source model: " + cast_value(read_attribute(core, model_id, "name")))
-		log("Target meta-model: " + cast_value(read_attribute(core, metamodel_id, "name")))
+		//log("No types found!")
+		//log("Source model: " + cast_value(read_attribute(core, model_id, "name")))
+		//log("Target meta-model: " + cast_value(read_attribute(core, metamodel_id, "name")))
 		return read_root()!
 		return read_root()!
 	
 	
 	choice = set_pop(all_links)
 	choice = set_pop(all_links)

+ 1 - 0
bootstrap/primitives.alc

@@ -56,3 +56,4 @@ Float function time() = ?primitives/time
 String function hash(a : String) = ?primitives/hash
 String function hash(a : String) = ?primitives/hash
 Float function __sleep(a : Float, b : Boolean) = ?primitives/__sleep
 Float function __sleep(a : Float, b : Boolean) = ?primitives/__sleep
 Boolean function is_error(a : Element) = ?primitives/is_error
 Boolean function is_error(a : Element) = ?primitives/is_error
+Element function list_sort(a : Element) = ?primitives/list_sort

+ 11 - 0
bootstrap/semi_primitives.alc

@@ -602,3 +602,14 @@ Element function list_delete(a : Element, b : Integer):
 
 
 	dict_delete(a, current)
 	dict_delete(a, current)
 	return a!
 	return a!
+
+Void function dict_update(a : Element, b : Element):
+	Element keys
+	String key
+
+	keys = dict_keys(b)
+	while (set_len(keys) > 0):
+		key = set_pop(keys)
+		dict_overwrite(a, key, b[key])
+
+	return!

+ 11 - 4
examples/multi_conformance.py

@@ -11,14 +11,20 @@ include "primitives.alh"
 
 
 SimpleAttribute integer {
 SimpleAttribute integer {
     constraint = $
     constraint = $
-        Boolean function constraint(value : Element):
-            return is_physical_int(value)!
+        String function constraint(value : Element):
+            if is_physical_int(value):
+                return "OK"!
+            else:
+                return "Expected integer value instead of '" + cast_string(value) + "'"!
         $
         $
 }
 }
 SimpleAttribute string {
 SimpleAttribute string {
     constraint = $
     constraint = $
-        Boolean function constraint(value : Element):
-            return is_physical_string(value)!
+        String function constraint(value : Element):
+            if is_physical_string(value):
+                return "OK"!
+            else:
+                return "Expected string value instead of '" + cast_string(value) + "'"!
         $
         $
 }
 }
 
 
@@ -59,6 +65,7 @@ print(model_types("models/model_string"))
 
 
 #print(verify("models/model_string", "formalisms/simple_mm", "models/conformance_AToMPM"))
 #print(verify("models/model_string", "formalisms/simple_mm", "models/conformance_AToMPM"))
 transformation_execute_AL("models/conformance_AToMPM", {"model": "models/model_integer", "metamodel": "formalisms/simple_mm", "type_mapping": model_types("models/model_integer").pop()[1]}, {})
 transformation_execute_AL("models/conformance_AToMPM", {"model": "models/model_integer", "metamodel": "formalisms/simple_mm", "type_mapping": model_types("models/model_integer").pop()[1]}, {})
+transformation_execute_AL("models/conformance_AToMPM", {"model": "models/model_string", "metamodel": "formalisms/simple_mm", "type_mapping": model_types("models/model_string").pop()[1]}, {})
 #print(verify("models/model_integer", "formalisms/simple_mm", "models/conformance_AToMPM"))
 #print(verify("models/model_integer", "formalisms/simple_mm", "models/conformance_AToMPM"))
 #print(verify("models/model_string", "formalisms/simple_mm", "models/conformance_MetaDepth"))
 #print(verify("models/model_string", "formalisms/simple_mm", "models/conformance_MetaDepth"))
 #print(verify("models/model_integer", "formalisms/simple_mm", "models/conformance_MetaDepth"))
 #print(verify("models/model_integer", "formalisms/simple_mm", "models/conformance_MetaDepth"))

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

@@ -95,6 +95,7 @@ Element function resolve(var_name : String)
 Boolean function has_input()
 Boolean function has_input()
 Element function list_pop(lst : Element, index : Integer)
 Element function list_pop(lst : Element, index : Integer)
 Element function list_pop_final(lst : Element)
 Element function list_pop_final(lst : Element)
+Element function list_sort(a : Element)
 Element function set_copy(set : Element)
 Element function set_copy(set : Element)
 String function set_to_string(set : Element)
 String function set_to_string(set : Element)
 String function list_to_string(set : Element)
 String function list_to_string(set : Element)
@@ -122,3 +123,4 @@ Element function dict_values(dict : Element)
 Boolean function is_error(a : Element)
 Boolean function is_error(a : Element)
 Element function range(max : Integer)
 Element function range(max : Integer)
 String function spawn(function : Element, arguments : Element)
 String function spawn(function : Element, arguments : Element)
+Void function dict_update(a : Element, b : Element)

+ 10 - 0
kernel/modelverse_kernel/primitives.py

@@ -430,3 +430,13 @@ def is_error(a, **remainder):
         yield [("RETURN", [{'value': True}])]
         yield [("RETURN", [{'value': True}])]
     else:
     else:
         yield [("RETURN", [{'value': False}])]
         yield [("RETURN", [{'value': False}])]
+
+def list_sort(a, **remainder):
+    elements, = yield [("RO", [a['id']])]
+    values = yield [("RD", [a['id'], i]) for i in range(elements)]
+    values = yield [("RV", [i]) for i in values]
+    new_list, = yield [("CN", [])]
+    values = yield [("CNV", [v]) for v in sorted(values))
+    yield [("CD", [new_list, i, v]) for i, v in enumerate(values)]
+
+    yield [("RETURN", [{'id': new_list}])]

+ 44 - 11
models/Conformance/AToMPM.alc

@@ -1,6 +1,7 @@
 include "primitives.alh"
 include "primitives.alh"
 include "object_operations.alh"
 include "object_operations.alh"
 include "modelling.alh"
 include "modelling.alh"
+include "library.alh"
 
 
 Boolean function main(model : Element):
 Boolean function main(model : Element):
 	// Contains three types of models: model, metamodel, and type_mapping.
 	// Contains three types of models: model, metamodel, and type_mapping.
@@ -10,13 +11,10 @@ Boolean function main(model : Element):
 	// Thus only the check for multiple inheritance is being done, which checks for attributes.
 	// Thus only the check for multiple inheritance is being done, which checks for attributes.
 	// A full example is given in the Modelverse's internal conformance relation.
 	// A full example is given in the Modelverse's internal conformance relation.
 
 
-	log("Performing conformance check!")
-
 	// Find all instances of classes
 	// Find all instances of classes
 	// First, find the class types
 	// First, find the class types
 	Element classes
 	Element classes
 	classes = allInstances(model, "metamodel/Class")
 	classes = allInstances(model, "metamodel/Class")
-	log("Got classes: " + set_to_string(classes))
 
 
 	Element links
 	Element links
 	String link
 	String link
@@ -28,23 +26,58 @@ Boolean function main(model : Element):
 	instances = allInstances(model, "type_mapping/Instance")
 	instances = allInstances(model, "type_mapping/Instance")
 	while (set_len(instances) > 0):
 	while (set_len(instances) > 0):
 		instance = set_pop(instances)
 		instance = set_pop(instances)
-		log("Found instance: " + instance)
-		log("   Connects to: " + cast_string(set_pop(allAssociationDestinations(model, instance, "type_mapping/TypeLink"))))
-		log("Association connects: " + instance + " --> " + cast_string(set_pop(allAssociationDestinations(model, instance, "type_mapping/TypeLink"))))
-		//dict_add(type_mapping, "model/" + string_replace(readAssociationSource(model, link), "type_mapping/instance_", ""), "metamodel/" + string_replace(readAssociationDestination(model, link), "type_mapping/type_", ""))
+		dict_add(type_mapping, "model/" + string_replace(instance, "type_mapping/instance_", ""), "metamodel/" + string_replace(set_pop(allAssociationDestinations(model, instance, "type_mapping/TypeLink")), "type_mapping/type_", ""))
 	
 	
-	log("Found type mapping: " + dict_to_string(type_mapping))
-
 	// Check if each attribute is there, and satisfies the constraints
 	// Check if each attribute is there, and satisfies the constraints
 	instances = dict_keys(type_mapping)
 	instances = dict_keys(type_mapping)
 	while (set_len(instances) > 0):
 	while (set_len(instances) > 0):
 		instance = set_pop(instances)
 		instance = set_pop(instances)
-		log("Found type: " + read_type(model, type_mapping[instance]))
 		if (read_type(model, type_mapping[instance]) == "metamodel/Class"):
 		if (read_type(model, type_mapping[instance]) == "metamodel/Class"):
 			// Got an instance of a Class
 			// Got an instance of a Class
-			log("Got a class instance: " + instance)
+			String type
+			Element inherits_from
+			type = type_mapping[instance]
+
+			Element outgoing_links
+			String outgoing_link
+			Element attrs
+
+			outgoing_links = allOutgoingAssociationInstances(model, instance, "")
+			attrs = dict_create()
+			while (set_len(outgoing_links) > 0):
+				outgoing_link = set_pop(outgoing_links)
+				String name
+				if (dict_in(type_mapping, outgoing_link)):
+					name = read_attribute(model, type_mapping[outgoing_link], "name")
+					dict_add(attrs, name, model["model"][readAssociationDestination(model, outgoing_link)])
 
 
 			// Fetch a list of attributes that should be defined
 			// Fetch a list of attributes that should be defined
 			// TODO
 			// TODO
+			inherits_from = allAssociationDestinations(model, type, "metamodel/Inheritance")
+
+			String superclass
+			Element defining_attributes
+			Element last_found
+
+			last_found = dict_create()
+			while (set_len(inherits_from) > 0):
+				superclass = set_pop(inherits_from)
+				defining_attributes = getInstantiatableAttributes(model, superclass, "metamodel/AttributeLink")
+				dict_update(last_found, defining_attributes)
+
+			Element keys
+			String attr
+			Element constraint
+			String result
+			keys = dict_keys(attrs)
+			while (set_len(keys) > 0):
+				attr = set_pop(keys)
+				constraint = get_func_AL_model(import_node(read_attribute(model, last_found[attr], "constraint")))
+				result = constraint(attrs[attr])
+
+				if (result != "OK"):
+					log("Conformance not OK: " + result)
+					return False!
 
 
+	log("Conformance OK")
 	return True!
 	return True!

+ 1 - 1
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)
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
 
-Date:   Fri May 25 13:34:41 2018
+Date:   Fri May 25 15:31:24 2018
 
 
 Model author: Yentl Van Tendeloo
 Model author: Yentl Van Tendeloo
 Model name:   MvK Server
 Model name:   MvK Server