فهرست منبع

Fixed is_nominal_subtype

Yentl Van Tendeloo 9 سال پیش
والد
کامیت
0853b0f64c
3فایلهای تغییر یافته به همراه84 افزوده شده و 95 حذف شده
  1. 54 83
      bootstrap/conformance_scd.alc
  2. 29 11
      integration/test_constructors_models.py
  3. 1 1
      interface/HUTN/includes/conformance_scd.alh

+ 54 - 83
bootstrap/conformance_scd.alc

@@ -3,56 +3,29 @@ include "library.alh"
 include "object_operations.alh"
 include "constructors.alh"
 
-Element function set_copy(elem_to_copy : Element):
-	Element result
-	Integer i
-	Integer max
-
-	result = create_node()
-
-	// Expand the provided list by including all elements that need to be checked
-	i = 0
-	max = read_nr_out(elem_to_copy)
-	while (i < max):
-		set_add(result, read_edge_dst(read_out(elem_to_copy, i)))
-		i = i + 1
-
-	return result
-
 Boolean function is_direct_instance(model : Element, instance : Element, type : Element):
 	// Just check whether or not the type mapping specifies the type as the type of the instance
 	return element_eq(dict_read_node(model["type_mapping"], instance), type)
 
 Boolean function is_nominal_instance(model : Element, instance : Element, type : Element):
-	return is_nominal_subtype(type, dict_read_node(model["type_mapping"], instance), model["metamodel"]["type_mapping"], model["inheritance"])
-
-Boolean function is_nominal_subtype(superclass : Element, subclass : Element, types : Element, inheritance_link : Element):
-	Integer counter
-	Integer i
-	Element edge
-	Element destination
+	return is_nominal_subtype(model["metamodel"], dict_read_node(model["type_mapping"], instance), type)
 
-	// End of recursion
-	if (element_eq(superclass, subclass)):
+Boolean function is_nominal_subtype(metamodel : Element, subclass : Element, superclass : Element):
+	if (element_eq(subclass, superclass)):
 		return True
 
-	// Iterate over all superclasses of the found class
-	counter = read_nr_out(subclass)
-	i = 0
-	while (i < counter):
-		edge = read_out(subclass, i)
-		// Check if it even has a type (to prevent errors)
-		if (dict_in_node(types, edge)):
-			// Check whether it is an inheritance edge, as there is no other distinction between them
-			if (element_eq(dict_read_node(types, edge), inheritance_link)):
-				// It is an inheritance edge, so follow it to its destination
-				destination = read_edge_dst(edge)
-				// Found a new superclass to test
-				if (is_nominal_subtype(superclass, destination, types, inheritance_link)):
-					return True
-		i = i + 1
+	Element superclasses
+	Element new_superclass
+	Element result
+
+	superclasses = get_superclasses(metamodel, subclass)
+
+	while (0 < list_len(superclasses)):
+		new_superclass = set_pop(superclasses)
+		result = is_nominal_subtype(metamodel, new_superclass, superclass)
+		if (result):
+			return True
 	
-	// No link seems to have been found, so it is False
 	return False
 
 Boolean function is_structural_instance(model : Element, instance : Element, type : Element):
@@ -97,53 +70,51 @@ Boolean function is_structural_subtype(subtype : Element, supertype : Element):
 
 String function conformance_scd(model : Element):
 	// Initialization
-	Element work_node
-	Element model_src
-	Element metamodel_src
-	Element model_dst
-	Element metamodel_dst
-	Element models
-	Element metamodels
-	models = set_copy(model["model"])
-
+	Element keys
+	Element metamodel
 	Element typing
+	String model_name
+	Element src_model
+	Element dst_model
+	Element src_metamodel
+	Element dst_metamodel
+	Element element
+
+	// Load in variables
+	keys = dict_keys(model["model"])
+	metamodel = model["metamodel"]
 	typing = model["type_mapping"]
-	metamodels = set_copy(model["metamodel"]["model"])
-	Element inheritance
-	inheritance = model["metamodel"]["inheritance"]
-	Element metamodel_typing
-	metamodel_typing = model["metamodel"]["type_mapping"]
-
-	// Iterate over all model elements and check if they are typed (in "typing") and their type is in the metamodel
-	while (dict_len(models) > 0):
-		work_node = set_pop(models)
-		// Basic check: does the element have a type
-		if (bool_not(dict_in_node(typing, work_node))):
-			return "Model has no type specified: " + getName(model, work_node)
-
-		// Basic check: is the type of the element part of the metamodel
-		if (bool_not(set_in_node(metamodels, dict_read_node(typing, work_node)))):
-			return "Type of element not in specified metamodel: " + getName(model, work_node)
-
-		// For edges only: check whether the source is typed according to the metamodel
-		if (is_edge(work_node)):
-			model_src = read_edge_src(work_node)
-			metamodel_src = read_edge_src(dict_read_node(typing, work_node))
-			log((getName(model, model_src) + " : ") + getName(model["metamodel"], metamodel_src))
-			if (bool_not(is_nominal_instance(model, model_src, metamodel_src))):
-				return "Source of model edge not typed by source of type: " + getName(model, work_node)
-
-		// For edges only: check whether the destination is typed according to the metamodel
-		if (is_edge(work_node)):
-			model_dst = read_edge_dst(work_node)
-			metamodel_dst = read_edge_dst(dict_read_node(typing, work_node))
-			if (bool_not(is_nominal_instance(model, model_dst, metamodel_dst))):
-				return "Destination of model edge not typed by destination of type: " + getName(model, work_node)
+
+	// Iterate over each element of the model, finding out whether everything is fine
+	while (0 < list_len(keys)):
+		model_name = set_pop(keys)
+		element = model["model"][model_name]
+
+		if (bool_not(dict_in_node(typing, element))):
+			return "Model has no type specified: " + model_name
+
+		if (bool_not(set_in_node(metamodel["model"], dict_read_node(typing, element)))):
+			return "Type of element not in specified metamodel: " + model_name
+
+		if (bool_not(is_nominal_instance(model, element, dict_read_node(typing, element)))):
+			return "Element is not an instance of its specified type: " + model_name
+
+		if (is_edge(element)):
+			src_model = read_edge_src(element)
+			dst_model = read_edge_dst(element)
+			src_metamodel = read_edge_src(dict_read_node(typing, element))
+			dst_metamodel = read_edge_dst(dict_read_node(typing, element))
+
+			if (bool_not(is_nominal_instance(model, src_model, src_metamodel))):
+				return "Source of model edge not typed by source of type: " + model_name
+
+			if (bool_not(is_nominal_instance(model, dst_model, dst_metamodel))):
+				return "Destination of model edge not typed by source of type: " + model_name
 
 	// Structure seems fine, now do static semantics
-	if (dict_in(model["metamodel"], "constraints")):
+	if (dict_in(metamodel, "constraints")):
 		Element constraint_function
-		constraint_function = model["metamodel"]["constraints"]
+		constraint_function = metamodel["constraints"]
 		return constraint_function(model)
 	else:
 		return "OK"

+ 29 - 11
integration/test_constructors_models.py

@@ -110,11 +110,11 @@ instantiate_example = [
         '"exit"',
     ]
 
-def is_direct_instance_call(model, metamodel):
+def conformance_call(operation, model, metamodel):
     return [
             '"output"',
                 '"call"',
-                    '"access"', '"resolve"', '"is_direct_instance"',
+                    '"access"', '"resolve"', '"%s"' % operation,
                     '3',
                     '"const"', 3,
                     '"call"',
@@ -144,15 +144,26 @@ def is_direct_instance_call(model, metamodel):
             ]
 
 is_direct_instance = \
-    is_direct_instance_call("a", "A") + \
-    is_direct_instance_call("b", "A") + \
-    is_direct_instance_call("c", "A") + \
-    is_direct_instance_call("a", "B") + \
-    is_direct_instance_call("b", "B") + \
-    is_direct_instance_call("c", "B") + \
-    is_direct_instance_call("a", "C") + \
-    is_direct_instance_call("b", "C") + \
-    is_direct_instance_call("c", "C")
+    conformance_call("is_direct_instance", "a", "A") + \
+    conformance_call("is_direct_instance", "b", "A") + \
+    conformance_call("is_direct_instance", "c", "A") + \
+    conformance_call("is_direct_instance", "a", "B") + \
+    conformance_call("is_direct_instance", "b", "B") + \
+    conformance_call("is_direct_instance", "c", "B") + \
+    conformance_call("is_direct_instance", "a", "C") + \
+    conformance_call("is_direct_instance", "b", "C") + \
+    conformance_call("is_direct_instance", "c", "C")
+
+is_nominal_instance = \
+    conformance_call("is_nominal_instance", "a", "A") + \
+    conformance_call("is_nominal_instance", "b", "A") + \
+    conformance_call("is_nominal_instance", "c", "A") + \
+    conformance_call("is_nominal_instance", "a", "B") + \
+    conformance_call("is_nominal_instance", "b", "B") + \
+    conformance_call("is_nominal_instance", "c", "B") + \
+    conformance_call("is_nominal_instance", "a", "C") + \
+    conformance_call("is_nominal_instance", "b", "C") + \
+    conformance_call("is_nominal_instance", "c", "C")
 
 def conformance_check(node):
     return [
@@ -188,3 +199,10 @@ class TestConstructorsModels(unittest.TestCase):
                     'False', 'True', 'False',
                     'False', 'False', 'True']
         self.assertTrue(run_barebone(commands, expected, 1))
+
+    def test_constructors_is_nominal_instance(self):
+        commands = bottom + retype + instantiate_example + is_nominal_instance + ['"return"', 'false']
+        expected = ['True', 'True', 'False',
+                    'False', 'True', 'False',
+                    'False', 'False', 'True']
+        self.assertTrue(run_barebone(commands, expected, 1))

+ 1 - 1
interface/HUTN/includes/conformance_scd.alh

@@ -1,6 +1,6 @@
 Boolean function is_direct_instance(a: Element, b: Element, c: Element)
 Boolean function is_nominal_instance(a: Element, b: Element, c: Element)
-Boolean function is_nominal_subtype(a: Element, b: Element, c: Element, d: Element)
+Boolean function is_nominal_subtype(a: Element, b: Element, c: Element)
 Boolean function is_structural_subtype(a: Element, b: Element)
 Boolean function is_structural_instance(a: Element, b: Element, c: Element)
 Element function conformance_scd(a: Element)