Browse Source

Implemented reverseKeyLookup as a primitive for significant performance boost

Yentl Van Tendeloo 9 years ago
parent
commit
eae0c8bbb4

+ 1 - 0
bootstrap/bootstrap.py

@@ -67,6 +67,7 @@ def bootstrap():
                     "dict_in": ["Boolean", "Element", "Element"],
                     "dict_in_node": ["Boolean", "Element", "Element"],
                     "dict_keys": ["Element", "Element"],
+                    "dict_reverse": ["Element", "Element", "Element"],
                     "set_add": ["Element", "Element", "Element"],
                     "set_pop": ["Element", "Element"],
                     "set_remove": ["Element", "Element", "Element"],

+ 52 - 55
bootstrap/conformance_scd.alc

@@ -17,7 +17,7 @@ Boolean function is_nominal_instance(model : Element, instance : String, type :
 		// Doesn't even have a type
 		return False
 
-	return is_nominal_subtype(model["metamodel"], getName(model["metamodel"], dict_read_node(model["type_mapping"], model["model"][instance])), type)
+	return is_nominal_subtype(model["metamodel"], reverseKeyLookup(model["metamodel"]["model"], dict_read_node(model["type_mapping"], model["model"][instance])), type)
 
 Boolean function is_nominal_subtype(metamodel : Element, subclass : String, superclass : String):
 	if (element_eq(metamodel["model"][subclass], metamodel["model"][superclass])):
@@ -76,7 +76,6 @@ String function conformance_scd(model : Element):
 
 		while (0 < list_len(keys)):
 			key = set_pop(keys)
-			log("Read cardinalities for " + key)
 			if (is_nominal_instance(metamodel, key, "Association")):
 				tmp_dict = create_node()
 				slc = read_attribute(metamodel, key, "source_lower_cardinality")
@@ -100,7 +99,6 @@ String function conformance_scd(model : Element):
 		keys = dict_keys(model["model"])
 		while (0 < list_len(keys)):
 			model_name = set_pop(keys)
-			log("Check element " + model_name)
 			element = model["model"][model_name]
 
 			if (bool_not(dict_in_node(typing, element))):
@@ -109,14 +107,14 @@ String function conformance_scd(model : Element):
 			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, model_name, getName(metamodel, dict_read_node(typing, element))))):
+			if (bool_not(is_nominal_instance(model, model_name, reverseKeyLookup(metamodel["model"], dict_read_node(typing, element))))):
 				return "Element is not an instance of its specified type: " + model_name
 
 			if (is_edge(element)):
-				src_model = getName(model, read_edge_src(element))
-				dst_model = getName(model, read_edge_dst(element))
-				src_metamodel = getName(metamodel, read_edge_src(dict_read_node(typing, element)))
-				dst_metamodel = getName(metamodel, read_edge_dst(dict_read_node(typing, element)))
+				src_model = reverseKeyLookup(model["model"], read_edge_src(element))
+				dst_model = reverseKeyLookup(model["model"], read_edge_dst(element))
+				src_metamodel = reverseKeyLookup(metamodel["model"], read_edge_src(dict_read_node(typing, element)))
+				dst_metamodel = reverseKeyLookup(metamodel["model"], 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
@@ -124,52 +122,52 @@ String function conformance_scd(model : Element):
 				if (bool_not(is_nominal_instance(model, dst_model, dst_metamodel))):
 					return "Destination of model edge not typed by source of type: " + model_name
 
-			// Check cardinality for all of our edges
-			//
-			//      SLC..SUC     TLC..TUC
-			//   A  ---------------------> B
-			//
-			// First the incoming, so we are at B in the above figure
-			Integer lower_val
-			Integer upper_val
-			Integer instances
-
-			check_list = selectPossibleOutgoing(model, model_name, dict_keys(cardinalities))
-			while (0 < list_len(check_list)):
-				check_type = set_pop(check_list)
-				if (dict_in(cardinalities, check_type)):
-					// Cardinalities defined for this association, so check them
-					lower_val = cardinalities[check_type]["tlc"]
-					upper_val = cardinalities[check_type]["tuc"]
-					instances = list_len(allOutgoingAssociationInstances(model, model_name, check_type))
-					if (dict_in(cardinalities[check_type], "tlc")):
-						// A lower cardinality was defined at the target
-						if (integer_gt(cardinalities[check_type]["tlc"], instances)):
-							return "Lower cardinality violation for outgoing edge at " + model_name
-					if (dict_in(cardinalities[check_type], "tuc")):
-						// An upper cardinality was defined at the target
-						if (integer_lt(cardinalities[check_type]["tuc"], instances)):
-							return "Upper cardinality violation for outgoing edge at " + model_name
-
-			// Identical, but for outgoing, and thus for A in the figure
-			check_list = selectPossibleIncoming(model, model_name, dict_keys(cardinalities))
-			while (0 < list_len(check_list)):
-				check_type = set_pop(check_list)
-				if (dict_in(cardinalities, check_type)):
-					// Cardinalities defined for this association, so check them
-					lower_val = cardinalities[check_type]["slc"]
-					upper_val = cardinalities[check_type]["suc"]
-					instances = list_len(allIncomingAssociationInstances(model, model_name, check_type))
-					if (dict_in(cardinalities[check_type], "slc")):
-						// A lower cardinality was defined at the source
-						if (integer_gt(cardinalities[check_type]["slc"], instances)):
-							return "Lower cardinality violation for incoming edge at " + model_name
-					if (dict_in(cardinalities[check_type], "suc")):
-						// An upper cardinality was defined at the source
-						if (integer_lt(cardinalities[check_type]["suc"], instances)):
-							return "Upper cardinality violation for incoming edge at " + model_name
-
-	log("Finished, checking multiplicities at the end")
+			if (dict_in(cardinalities, model_name)):
+				// Check cardinality for all of our edges
+				//
+				//      SLC..SUC     TLC..TUC
+				//   A  ---------------------> B
+				//
+				// First the incoming, so we are at B in the above figure
+				Integer lower_val
+				Integer upper_val
+				Integer instances
+
+				check_list = selectPossibleOutgoing(model, model_name, dict_keys(cardinalities))
+				while (0 < list_len(check_list)):
+					check_type = set_pop(check_list)
+					if (dict_in(cardinalities, check_type)):
+						// Cardinalities defined for this association, so check them
+						lower_val = cardinalities[check_type]["tlc"]
+						upper_val = cardinalities[check_type]["tuc"]
+						instances = list_len(allOutgoingAssociationInstances(model, model_name, check_type))
+						if (dict_in(cardinalities[check_type], "tlc")):
+							// A lower cardinality was defined at the target
+							if (integer_gt(cardinalities[check_type]["tlc"], instances)):
+								return "Lower cardinality violation for outgoing edge at " + model_name
+						if (dict_in(cardinalities[check_type], "tuc")):
+							// An upper cardinality was defined at the target
+							if (integer_lt(cardinalities[check_type]["tuc"], instances)):
+								return "Upper cardinality violation for outgoing edge at " + model_name
+
+				// Identical, but for outgoing, and thus for A in the figure
+				check_list = selectPossibleIncoming(model, model_name, dict_keys(cardinalities))
+				while (0 < list_len(check_list)):
+					check_type = set_pop(check_list)
+					if (dict_in(cardinalities, check_type)):
+						// Cardinalities defined for this association, so check them
+						lower_val = cardinalities[check_type]["slc"]
+						upper_val = cardinalities[check_type]["suc"]
+						instances = list_len(allIncomingAssociationInstances(model, model_name, check_type))
+						if (dict_in(cardinalities[check_type], "slc")):
+							// A lower cardinality was defined at the source
+							if (integer_gt(cardinalities[check_type]["slc"], instances)):
+								return "Lower cardinality violation for incoming edge at " + model_name
+						if (dict_in(cardinalities[check_type], "suc")):
+							// An upper cardinality was defined at the source
+							if (integer_lt(cardinalities[check_type]["suc"], instances)):
+								return "Upper cardinality violation for incoming edge at " + model_name
+
 	// Check multiplicities, if they are defined (optional)
 	Element metamodel_keys
 	String metamodel_element
@@ -178,7 +176,6 @@ String function conformance_scd(model : Element):
 	metamodel_keys = dict_keys(metamodel["model"])
 	while (0 < list_len(metamodel_keys)):
 		metamodel_element = set_pop(metamodel_keys)
-		log("Check " + metamodel_element)
 
 		// Lower multiplicities
 		attr_value = read_attribute(metamodel, metamodel_element, "lower_cardinality")

+ 11 - 4
bootstrap/modelling.alc

@@ -50,6 +50,13 @@ String function model_add_edge(model : Element, name : String, source : String,
 	Element new_edge
 	String actual_name
 	
+	if (bool_not(dict_in(model["model"], source))):
+		log("ERROR: source of link unknown")
+		return ""
+	if (bool_not(dict_in(model["model"], destination))):
+		log("ERROR: destination of link unknown")
+		return ""
+
 	new_edge = create_edge(model["model"][source], model["model"][destination])
 	actual_name = instantiated_name(new_edge, name)
 	dict_add(model["model"], actual_name, new_edge)
@@ -94,14 +101,14 @@ String function find_attribute_type(model : Element, elem : String, name : Strin
 	String mm_elem
 	String direct_type
 
-	direct_type = getName(model["metamodel"], dict_read_node(model["type_mapping"], model["model"][elem]))
+	direct_type = reverseKeyLookup(model["metamodel"]["model"], dict_read_node(model["type_mapping"], model["model"][elem]))
 	mm_elem = find_attribute_definer(model["metamodel"], direct_type, name)
 
 	if (value_eq(mm_elem, "")):
 		// Couldn't find element, so is not allowed!
 		return ""
 	else:
-		return getName(model["metamodel"], dict_read_edge(model["metamodel"]["model"][mm_elem], name))
+		return reverseKeyLookup(model["metamodel"]["model"], dict_read_edge(model["metamodel"]["model"][mm_elem], name))
 
 Element function get_superclasses(model : Element, name : String):
 	Element result
@@ -121,7 +128,7 @@ Element function get_superclasses(model : Element, name : String):
 	while (i < num_edges):
 		edge = read_out(elem, i)
 		if (element_eq(dict_read_node(model["type_mapping"], edge), model["inheritance"])):
-			create_edge(result, getName(model, read_edge_dst(edge)))
+			create_edge(result, reverseKeyLookup(model["model"], read_edge_dst(edge)))
 		i = i + 1
 
 	return result
@@ -160,7 +167,7 @@ Void function instantiate_attribute(model : Element, element : String, attribute
 		return
 		
 	attr_name = model_add_value(model, "", value)
-	retype(model, attr_name, getName(model["metamodel"], read_edge_dst(model["metamodel"]["model"][attr_type])))
+	retype(model, attr_name, reverseKeyLookup(model["metamodel"]["model"], read_edge_dst(model["metamodel"]["model"][attr_type])))
 	instantiate_link(model, attr_type, "", element, attr_name)
 
 	return

+ 8 - 5
bootstrap/object_operations.alc

@@ -123,7 +123,7 @@ Element function getAttributeList(model : Element, element : String):
 	while (0 < list_len(keys)):
 		attr_name = set_pop(keys)
 		if (is_physical_string(attr_name)):
-			attr_type = getName(model["metamodel"], type[attr_name])
+			attr_type = reverseKeyLookup(model["metamodel"]["model"], type[attr_name])
 			dict_add(result, attr_name, attr_type)
 
 	// Go on to the metalevel
@@ -145,15 +145,15 @@ Element function getInstantiatableAttributes(model : Element, element : String):
 	while (0 < read_nr_out(set_own)):
 		e = set_pop(set_own)
 		if (is_physical_string(e)):
-			dict_add(result, e, getName(model, element[e]))
+			dict_add(result, e, reverseKeyLookup(model["model"], element[e]))
 
 	return result
 
-String function getName(model : Element, element : Element):
-	return reverseKeyLookup(model["model"], element)
-
 // TODO Utility functions!
 String function reverseKeyLookup(dict : Element, element : Element):
+	return dict_reverse(dict, element)
+
+	// TODO this code makes everything very inefficient; wait to enable this for once the compilation is implemented
 	Element elements
 	String name
 
@@ -179,3 +179,6 @@ String function print_dict(dict : Element):
 		result = result + cast_v2s(dict[key])
 		result = result + "\n"
 	return result
+
+String function getName(model : Element, element : Element):
+	return reverseKeyLookup(model["model"], element)

+ 1 - 0
bootstrap/primitives.alc

@@ -78,6 +78,7 @@ Boolean function is_physical_float(a: Element) = ?primitives/is_physical_float
 Boolean function is_physical_string(a: Element) = ?primitives/is_physical_string
 Boolean function is_physical_boolean(a: Element) = ?primitives/is_physical_boolean
 Boolean function is_physical_action(a: Element) = ?primitives/is_physical_action
+Element function dict_reverse(a: Element, b: Element) = ?primitives/dict_reverse
 
 Element function exec(first_instr : Element):
 	// This does very ugly things, so beware!

+ 1 - 1
hybrid_server/classes/mvkcontroller.xml

@@ -175,7 +175,7 @@
                         </raise>
                     </transition>
 
-                    <transition cond="self.timeout and self.destination is None" after="self.sccd_yield()" target="."/>
+                    <transition cond="self.timeout and self.destination is None" after="self.sccd_yield() + 0.05" target="."/>
 
                     <transition cond="not self.timeout and self.destination is None" after="self.sccd_yield()" target="."/>
                 </state>

+ 7 - 6
integration/test_constructors_models.py

@@ -80,6 +80,7 @@ action_language = [
         '"instantiate_node"', 1, '"Class"', '"Constant"',
         '"instantiate_node"', 1, '"Class"', '"Input"',
         '"instantiate_node"', 1, '"Class"', '"Resolve"',
+        '"instantiate_node"', 1, '"Class"', '"Call"',
         '"instantiate_link"', 1, '"Inheritance"', '""', '"Funcdef"', '"Any"',
         '"instantiate_link"', 1, '"Inheritance"', '""', '"Action"', '"Any"',
         '"instantiate_link"', 1, '"Inheritance"', '""', '"Param"', '"Any"',
@@ -115,12 +116,6 @@ action_language = [
         '"instantiate_attribute"', 1, '"assign_var"', '"name"', '"var"',
         '"instantiate_link"', 1, '"Association"', '"assign_value"', '"Assign"', '"Expression"',
         '"instantiate_attribute"', 1, '"assign_value"', '"name"', '"value"',
-        '"instantiate_link"', 1, '"Association"', '"call_func"', '"Call"', '"Expression"',
-        '"instantiate_attribute"', 1, '"call_func"', '"name"', '"func"',
-        '"instantiate_link"', 1, '"Association"', '"call_params"', '"Call"', '"Param"',
-        '"instantiate_attribute"', 1, '"call_params"', '"name"', '"params"',
-        '"instantiate_link"', 1, '"Association"', '"call_last_param"', '"Call"', '"Param"',
-        '"instantiate_attribute"', 1, '"call_last_param"', '"name"', '"last_param"',
         '"instantiate_link"', 1, '"Association"', '"break_while"', '"Break"', '"While"',
         '"instantiate_attribute"', 1, '"break_while"', '"name"', '"while"',
         '"instantiate_link"', 1, '"Association"', '"continue_while"', '"Continue"', '"While"',
@@ -145,6 +140,12 @@ action_language = [
         '"instantiate_attribute"', 1, '"param_next_param"', '"name"', '"next_param"',
         '"instantiate_link"', 1, '"Association"', '"funcdef_body"', '"Funcdef"', '"Statement"',
         '"instantiate_attribute"', 1, '"funcdef_body"', '"name"', '"body"',
+        '"instantiate_link"', 1, '"Association"', '"call_func"', '"Call"', '"Expression"',
+        '"instantiate_attribute"', 1, '"call_func"', '"name"', '"func"',
+        '"instantiate_link"', 1, '"Association"', '"call_params"', '"Call"', '"Param"',
+        '"instantiate_attribute"', 1, '"call_params"', '"name"', '"params"',
+        '"instantiate_link"', 1, '"Association"', '"call_last_param"', '"Call"', '"Param"',
+        '"instantiate_attribute"', 1, '"call_last_param"', '"name"', '"last_param"',
         '"exit"',
     ]
 

+ 1 - 1
integration/utils.py

@@ -274,7 +274,7 @@ def run_barebone(parameters, expected, interface="0", timeout=False, wait=False,
                         # Modelverse has already terminated, which isn't a good sign!
                         return False
 
-                    val = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username})), timeout=45).read()
+                    val = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username})), timeout=120).read()
                 except:
                     if timeout:
                         return True

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

@@ -88,3 +88,4 @@ Boolean function is_physical_string(a : Element)
 Boolean function is_physical_action(a : Element)
 Boolean function is_physical_boolean(a : Element)
 Boolean function has_value(a : Element)
+Element function dict_reverse(a : Element, b : Element)

+ 10 - 0
kernel/modelverse_kernel/primitives.py

@@ -302,6 +302,16 @@ def dict_keys(a, **remainder):
     yield [("CE", [result, v]) for v in keys]
     raise PrimitiveFinished(result)
 
+def dict_reverse(a, b, **remainder):
+    keys = yield [("RDK", [a])]
+    keys = list(keys)
+    values = yield [("RDN", [a, i]) for i in keys]
+    for i, v in enumerate(values):
+        if v == b:
+            raise PrimitiveFinished(keys[i])
+    result = yield [("CNV", ["(unknown: %s)" % b])]
+    raise PrimitiveFinished(result)
+
 def is_physical_int(a, **remainder):
     t = yield [("RV", [a])]
     result = yield [("CNV", [isinstance(t, int) or isinstance(t, long)])]