Sfoglia il codice sorgente

Merge branch 'yentl' into new-sccd

Yentl Van Tendeloo 9 anni fa
parent
commit
e832699d94

+ 75 - 44
bootstrap/conformance_scd.alc

@@ -9,6 +9,10 @@ Boolean function is_direct_instance(model : Element, instance : Element, type :
 	return element_eq(dict_read_node(model["type_mapping"], instance), type)
 
 Boolean function is_nominal_instance(model : Element, instance : Element, type : Element):
+	if (bool_not(set_in_node(model["metamodel"]["model"], type))):
+		// type is not even in the specified metamodel, so this will never work
+		return False
+
 	return is_nominal_subtype(model["metamodel"], dict_read_node(model["type_mapping"], instance), type)
 
 Boolean function is_nominal_subtype(metamodel : Element, subclass : Element, superclass : Element):
@@ -19,7 +23,6 @@ Boolean function is_nominal_subtype(metamodel : Element, subclass : Element, sup
 	Element new_superclass
 	Element result
 
-	log((("Nominal subtype? " + cast_e2s(subclass)) + " --|> ") + cast_e2s(superclass))
 	superclasses = get_superclasses(metamodel, subclass)
 
 	while (0 < list_len(superclasses)):
@@ -83,13 +86,45 @@ String function conformance_scd(model : Element):
 	Element element
 	Element check_list
 	Element check_type
+	Element cardinalities
+	Element scd
 
 	// Load in variables
-	keys = dict_keys(model["model"])
+	scd = import_node("models/SimpleClassDiagrams")
 	metamodel = model["metamodel"]
 	typing = model["type_mapping"]
+	cardinalities = create_node()
+
+	// Create dictionary with all associations and allowed cardinalities
+	keys = dict_keys(metamodel["model"])
+	Integer slc
+	Integer suc
+	Integer tlc
+	Integer tuc
+	String key
+	Element tmp_dict
+	while (0 < list_len(keys)):
+		key = set_pop(keys)
+		if (is_nominal_instance(metamodel, metamodel["model"][key], scd["model"]["Association"])):
+			tmp_dict = create_node()
+			slc = read_attribute(metamodel, key, "source_lower_cardinality")
+			suc = read_attribute(metamodel, key, "source_upper_cardinality")
+			tlc = read_attribute(metamodel, key, "target_lower_cardinality")
+			tuc = read_attribute(metamodel, key, "target_upper_cardinality")
+			if (element_neq(slc, read_root())):
+				dict_add(tmp_dict, "slc", slc)
+			if (element_neq(suc, read_root())):
+				dict_add(tmp_dict, "suc", suc)
+			if (element_neq(tlc, read_root())):
+				dict_add(tmp_dict, "tlc", tlc)
+			if (element_neq(tuc, read_root())):
+				dict_add(tmp_dict, "tuc", tuc)
+
+			if (list_len(tmp_dict) > 0):
+				dict_add(cardinalities, key, tmp_dict)
 
 	// Iterate over each element of the model, finding out whether everything is fine
+	keys = dict_keys(model["model"])
 	while (0 < list_len(keys)):
 		model_name = set_pop(keys)
 		element = model["model"][model_name]
@@ -121,48 +156,44 @@ String function conformance_scd(model : Element):
 		//   A  ---------------------> B
 		//
 		// First the incoming, so we are at B in the above figure
-		check_list = allPossibleIncoming(model, model_name)
+		Integer lower_val
+		Integer upper_val
+		Integer instances
+
+		check_list = selectPossibleIncoming(model, model_name, dict_keys(cardinalities))
 		while (0 < list_len(check_list)):
-			Integer instances
-			Integer lower_val
-			Integer upper_val
 			check_type = set_pop(check_list)
-			log("Lookup!")
-			log(cast_e2s(check_type))
-			log(cast_e2s(reverseNameLookup(model, check_type)))
-			log(cast_e2s(reverseNameLookup(metamodel, check_type)))
-			lower_val = read_attribute(metamodel, reverseNameLookup(metamodel, check_type), "target_lower_cardinality")
-			upper_val = read_attribute(metamodel, reverseNameLookup(metamodel, check_type), "target_upper_cardinality")
-			log("Look up " + cast_e2s(element))
-			log("   " + cast_e2s(check_type))
-			instances = list_len(allIncomingAssociationInstances(model, element, check_type))
-			if (element_neq(lower_val, read_root())):
-				// A lower multiplicity was defined at the target
-				if (lower_val > instances):
-					return "Lower cardinality violation for incoming edge at " + model_name
-			if (element_neq(upper_val, read_root())):
-				// A lower multiplicity was defined at the target
-				if (upper_val < instances):
-					return "Upper cardinality violation for incoming edge at " + model_name
+			if (dict_in(cardinalities, reverseKeyLookup(metamodel["model"], check_type))):
+				// Cardinalities defined for this association, so check them
+				lower_val = cardinalities[check_type]["tlc"]
+				upper_val = cardinalities[check_type]["tlc"]
+				instances = list_len(allIncomingAssociationInstances(model, element, 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 incoming edge at " + model_name
+				if (dict_in(cardinalities[check_type], "tuc")):
+					// An upper cardinality was defined at the target
+					if (integer_gt(cardinalities[check_type]["tuc"], instances)):
+						return "Upper cardinality violation for incoming edge at " + model_name
 
 		// Identical, but for outgoing, and thus for A in the figure
-		check_list = allPossibleOutgoing(model, model_name)
+		check_list = selectPossibleOutgoing(model, model_name, dict_keys(cardinalities))
 		while (0 < list_len(check_list)):
-			Integer instances
-			Integer lower_val
-			Integer upper_val
 			check_type = set_pop(check_list)
-			lower_val = read_attribute(metamodel, reverseNameLookup(metamodel, check_type), "source_lower_cardinality")
-			upper_val = read_attribute(metamodel, reverseNameLookup(metamodel, check_type), "source_upper_cardinality")
-			instances = list_len(allOutgoingAssociationInstances(model, element, check_type))
-			if (element_neq(lower_val, read_root())):
-				// A lower multiplicity was defined at the source
-				if (lower_val > instances):
-					return "Lower cardinality violation for incoming edge at " + model_name
-			if (element_neq(upper_val, read_root())):
-				// A lower multiplicity was defined at the source
-				if (upper_val < instances):
-					return "Upper cardinality violation for incoming edge at " + model_name
+			if (dict_in(cardinalities, reverseKeyLookup(metamodel["model"], check_type))):
+				// Cardinalities defined for this association, so check them
+				lower_val = cardinalities[check_type]["slc"]
+				upper_val = cardinalities[check_type]["slc"]
+				instances = list_len(allOutgoingAssociationInstances(model, element, 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 outgoing edge at " + model_name
+				if (dict_in(cardinalities[check_type], "suc")):
+					// An upper cardinality was defined at the source
+					if (integer_gt(cardinalities[check_type]["suc"], instances)):
+						return "Upper cardinality violation for outgoing edge at " + model_name
 
 	// Check multiplicities, if they are defined (optional)
 	Element metamodel_keys
@@ -174,18 +205,18 @@ String function conformance_scd(model : Element):
 		metamodel_element = set_pop(metamodel_keys)
 
 		// Lower multiplicities
-		attr_value = read_attribute(metamodel, metamodel_element, "lower_multiplicity")
+		attr_value = read_attribute(metamodel, metamodel_element, "lower_cardinality")
 		if (element_neq(attr_value, read_root())):
-			// We have defined a lower multiplicity, so check number of instances!
+			// We have defined a lower cardinality, so check number of instances!
 			if (attr_value > list_len(allInstances(model, metamodel["model"][metamodel_element]))):
-				return "Lower multiplicity violated for class: " + metamodel_element
+				return "Lower cardinality violated for class: " + metamodel_element
 
 		// Upper multiplicities
-		attr_value = read_attribute(metamodel, metamodel_element, "upper_multiplicity")
+		attr_value = read_attribute(metamodel, metamodel_element, "upper_cardinality")
 		if (element_neq(attr_value, read_root())):
-			// We have defined a lower multiplicity, so check number of instances!
+			// We have defined a lower cardinality, so check number of instances!
 			if (attr_value < list_len(allInstances(model, metamodel["model"][metamodel_element]))):
-				return "Upper multiplicity violated for class: " + metamodel_element
+				return "Upper cardinality violated for class: " + metamodel_element
 
 	// Structure seems fine, now do static semantics
 	if (dict_in(metamodel, "constraints")):

+ 19 - 61
bootstrap/metamodels.alc

@@ -26,32 +26,6 @@ Element function create_metamodels():
 		model_add_edge(scd, "attr_name", "association_attr", "name")
 		model_add_node(scd, "Integer")
 
-		// TODO: possible to use instantiate_named here?
-		// Lower multiplicity on classes
-		model_add_value(scd, "lower_multiplicity", "lower_multiplicity")
-		model_add_edge(scd, "class_to_lm", "Class", "Integer")
-		model_add_edge(scd, "lm_name", "class_to_lm", "lower_multiplicity")
-		// Upper multiplicity on classes
-		model_add_value(scd, "upper_multiplicity", "upper_multiplicity")
-		model_add_edge(scd, "class_to_um", "Class", "Integer")
-		model_add_edge(scd, "um_name", "class_to_um", "upper_multiplicity")
-		// Source lower multiplicity on associations
-		model_add_value(scd, "source_lower_cardinality", "source_lower_cardinality")
-		model_add_edge(scd, "assoc_to_slc", "Association", "Integer")
-		model_add_edge(scd, "slc_name", "assoc_to_slc", "source_lower_cardinality")
-		// Source upper multiplicity on associations
-		model_add_value(scd, "source_upper_cardinality", "source_upper_cardinality")
-		model_add_edge(scd, "assoc_to_suc", "Association", "Integer")
-		model_add_edge(scd, "suc_name", "assoc_to_suc", "source_upper_cardinality")
-		// Target lower multiplicity on associations
-		model_add_value(scd, "target_lower_cardinality", "target_lower_cardinality")
-		model_add_edge(scd, "assoc_to_tlc", "Association", "Integer")
-		model_add_edge(scd, "tlc_name", "assoc_to_tlc", "target_lower_cardinality")
-		// Target upper multiplicity on associations
-		model_add_value(scd, "target_upper_cardinality", "target_upper_cardinality")
-		model_add_edge(scd, "assoc_to_tuc", "Association", "Integer")
-		model_add_edge(scd, "tuc_name", "assoc_to_tuc", "target_upper_cardinality")
-
 		retype_model(scd, scd)
 		define_inheritance(scd, "Inheritance")
 		retype(scd, "Class", "Class")
@@ -71,39 +45,20 @@ Element function create_metamodels():
 		retype(scd, "association_attr", "Association")
 		retype(scd, "attr_name", "association_attr")
 		retype(scd, "Integer", "Type")
-		// TODO: with instantiate_named, after all previous retypings?
-		// Lower multiplicity on classes
-		retype(scd, "lower_multiplicity", "String")
-		retype(scd, "lm_name", "association_attr")
-		retype(scd, "class_to_um", "Association")
-		// Upper multiplicity on classes
-		retype(scd, "upper_multiplicity", "String")
-		retype(scd, "class_to_lm", "Association")
-		retype(scd, "um_name", "association_attr")
-		// Source lower cardinality on associations
-		retype(scd, "source_lower_cardinality", "String")
-		retype(scd, "assoc_to_slc", "Association")
-		retype(scd, "slc_name", "association_attr")
-		// Source upper cardinality on associations
-		retype(scd, "source_upper_cardinality", "String")
-		retype(scd, "assoc_to_suc", "Association")
-		retype(scd, "suc_name", "association_attr")
-		// Target lower cardinality on associations
-		retype(scd, "target_lower_cardinality", "String")
-		retype(scd, "assoc_to_tlc", "Association")
-		retype(scd, "tlc_name", "association_attr")
-		// Target upper cardinality on associations
-		retype(scd, "target_upper_cardinality", "String")
-		retype(scd, "assoc_to_tuc", "Association")
-		retype(scd, "tuc_name", "association_attr")
 
-		// TODO: try this
-		//instantiate_named(scd, "Association", "lower_multiplicity", "Class", "Integer")
-		//instantiate_named(scd, "Association", "upper_multiplicity", "Class", "Integer")
-		//instantiate_named(scd, "Association", "source_lower_multiplicity", "Association", "Integer")
-		//instantiate_named(scd, "Association", "source_upper_multiplicity", "Association", "Integer")
-		//instantiate_named(scd, "Association", "target_lower_multiplicity", "Association", "Integer")
-		//instantiate_named(scd, "Association", "target_upper_multiplicity", "Association", "Integer")
+		// Add some attributes "the nice way" now that everything is typed
+		instantiate_link(scd, "Association", "lc", "Class", "Integer")
+		instantiate_attribute(scd, "lc", "name", "lower_cardinality")
+		instantiate_link(scd, "Association", "uc", "Class", "Integer")
+		instantiate_attribute(scd, "uc", "name", "upper_cardinality")
+		instantiate_link(scd, "Association", "slc", "Association", "Integer")
+		instantiate_attribute(scd, "slc", "name", "source_lower_cardinality")
+		instantiate_link(scd, "Association", "suc", "Association", "Integer")
+		instantiate_attribute(scd, "suc", "name", "source_upper_cardinality")
+		instantiate_link(scd, "Association", "tlc", "Association", "Integer")
+		instantiate_attribute(scd, "tlc", "name", "target_lower_cardinality")
+		instantiate_link(scd, "Association", "tuc", "Association", "Integer")
+		instantiate_attribute(scd, "tuc", "name", "target_upper_cardinality")
 
 		export_node("models/SimpleClassDiagrams", scd)
 
@@ -115,9 +70,12 @@ Element function create_metamodels():
 		instantiate_node(pn, "Type", "Integer")
 		instantiate_link(pn, "Association", "P2T", "Place", "Transition")
 		instantiate_link(pn, "Association", "T2P", "Transition", "Place")
-		instantiate_named(pn, "Association", "tokens", "Place", "Integer")
-		instantiate_named(pn, "Association", "weight", "P2T", "Integer")
-		instantiate_named(pn, "Association", "weight", "T2P", "Integer")
+		instantiate_link(pn, "Association", "Place_tokens", "Place", "Integer")
+		instantiate_attribute(pn, "Place_tokens", "name", "tokens")
+		instantiate_link(pn, "Association", "P2T_weight", "P2T", "Integer")
+		instantiate_attribute(pn, "P2T_weight", "name", "weight")
+		instantiate_link(pn, "Association", "T2P_weight", "T2P", "Integer")
+		instantiate_attribute(pn, "T2P_weight", "name", "weight")
 
 		set_model_constraints(pn, petrinet_constraints)
 		export_node("models/PetriNets", pn)

+ 7 - 18
bootstrap/modelling.alc

@@ -94,12 +94,13 @@ Element function find_attribute_type(model : Element, elem : String, name : Stri
 	Element mm_elem
 	Element direct_type
 
+	log("Search for type of " + elem)
 	direct_type = dict_read_node(model["type_mapping"], model["model"][elem])
+	log("Direct type: " + cast_e2s(direct_type))
 	mm_elem = find_attribute_definer(model["metamodel"], direct_type, name)
 
 	if (element_eq(mm_elem, read_root())):
 		// Couldn't find element, so is not allowed!
-		log("Undefined attribute!")
 		return read_root()
 	else:
 		return getName(model["metamodel"], dict_read_edge(mm_elem, name))
@@ -115,11 +116,10 @@ Element function get_superclasses(model : Element, elem : Element):
 	i = 0
 
 	// Read out all outgoing edges
+	log(cast_e2s(elem))
 	num_edges = read_nr_out(elem)
-	log(cast_i2s(num_edges))
 	while (i < num_edges):
 		edge = read_out(elem, i)
-		log(cast_e2s(edge))
 		if (element_eq(dict_read_node(model["type_mapping"], edge), model["inheritance"])):
 			create_edge(result, read_edge_dst(edge))
 		i = i + 1
@@ -136,6 +136,8 @@ Element function find_attribute_definer(model : Element, elem : Element, name :
 		Element current
 		Element found
 
+		log("Finding for element " + cast_e2s(elem))
+
 		superclasses = get_superclasses(model, elem)
 		while (list_len(superclasses) > 0):
 			current = set_pop(superclasses)
@@ -153,7 +155,9 @@ Void function instantiate_attribute(model : Element, element : String, attribute
 	String attr_type
 	String attr_name
 
+	log("Instantiating attribute " + attribute_name)
 	attr_type = find_attribute_type(model, element, attribute_name)
+	log("DONE")
 	attr_name = model_add_value(model, "", value)
 	retype(model, attr_name, getName(model["metamodel"], read_edge_dst(model["metamodel"]["model"][attr_type])))
 	instantiate_link(model, attr_type, "", element, attr_name)
@@ -169,18 +173,6 @@ String function instantiate_link(model : Element, type : String, name : String,
 
 	return actual_name
 
-Void function instantiate_named(model : Element, type : String, name : String, source : String, destination : String):
-	// Special helper function to create an edge and name it
-	String link_name
-	String name_name
-
-	link_name = instantiate_link(model, type, "", source, destination)
-	//name_name = model_add_value(model, "", name)
-	//retype(model, name_name, "String")
-	instantiate_attribute(model, link_name, "name", name)
-
-	return
-
 Void function define_inheritance(model : Element, inheritance_name : String):
 	// Set the inheritance link to the one defined in our own metamodel, given by the specified name
 	dict_add(model, "inheritance", model["metamodel"]["model"][inheritance_name])
@@ -210,7 +202,6 @@ Element function read_attribute(model : Element, element : String, attribute : S
 		attr_link = set_pop(attr_links)
 		return read_edge_dst(attr_link)
 
-	log("Could not find attribute!")
 	return read_root()
 
 Void function unset_attribute(model : Element, element : String, attribute : String):
@@ -252,8 +243,6 @@ Void function construct_model():
 			output(instantiate_model(input()))
 		elif (command == "instantiate_node"):
 			instantiate_node(input(), input(), input())
-		elif (command == "instantiate_named"):
-			instantiate_named(input(), input(), input(), input(), input())
 		elif (command == "instantiate_attribute"):
 			instantiate_attribute(input(), input(), input(), input())
 		elif (command == "instantiate_link"):

+ 18 - 23
bootstrap/object_operations.alc

@@ -25,10 +25,10 @@ Element function allInstances(model : Element, type : Element):
 	
 	return result
 
-Element function allPossibleIncoming(model : Element, target : String):
+Element function selectPossibleIncoming(model : Element, target : String, limit_set : Element):
 	// Find all possible incoming link types for the target model
 	// Should also include those specified on the superclass(es)
-	Element all_elems
+
 	String type
 	Element metamodel
 	Element elem
@@ -36,10 +36,9 @@ Element function allPossibleIncoming(model : Element, target : String):
 
 	result = create_node()
 	metamodel = model["metamodel"]
-	all_elems = dict_keys(metamodel["model"])
-	
-	while (0 < list_len(all_elems)):
-		type = set_pop(all_elems)
+
+	while (0 < list_len(limit_set)):
+		type = set_pop(limit_set)
 		elem = metamodel["model"][type]
 		if (is_edge(elem)):
 			if (is_nominal_instance(model, model["model"][target], read_edge_src(elem))):
@@ -47,10 +46,9 @@ Element function allPossibleIncoming(model : Element, target : String):
 	
 	return result
 
-Element function allPossibleOutgoing(model : Element, source : String):
+Element function selectPossibleOutgoing(model : Element, source : String, limit_set : Element):
 	// Find all possible outgoing link types for the source model
 	// Should also include those specified on the superclass(es)
-	Element all_elems
 	String type
 	Element metamodel
 	Element elem
@@ -58,10 +56,9 @@ Element function allPossibleOutgoing(model : Element, source : String):
 
 	result = create_node()
 	metamodel = model["metamodel"]
-	all_elems = dict_keys(model["metamodel"]["model"])
 	
-	while (0 < list_len(all_elems)):
-		type = set_pop(all_elems)
+	while (0 < list_len(limit_set)):
+		type = set_pop(limit_set)
 		elem = metamodel["model"][type]
 		if (is_edge(elem)):
 			if (is_nominal_instance(model, model["model"][source], read_edge_dst(elem))):
@@ -120,10 +117,7 @@ Element function getAttributeList(model : Element, element : String):
 	// Add our own attributes
 	while (0 < list_len(keys)):
 		attr_name = set_pop(keys)
-		log("Test for " + cast_e2s(attr_name))
 		if (is_physical_string(attr_name)):
-			log("Found attribute " + cast_v2s(attr_name))
-
 			attr_type = getName(model["metamodel"], type[attr_name])
 			dict_add(result, attr_name, attr_type)
 
@@ -162,16 +156,17 @@ String function getName(m : Element, e : Element):
 
 	return string_join(string_join("(unknown: ", cast_e2s(e)), " )")
 
-String function reverseNameLookup(s : Element, e : Element):
-	Element element_keys
-	element_keys = dict_keys(s)
+String function reverseKeyLookup(dict : Element, element : Element):
+	Element elements
+	String name
 
-	Element key
-	while (0 < read_nr_out(element_keys)):
-		key = set_pop(element_keys)
-		if (element_eq(dict_read_node(s, key), e)):
-			return key
-	return string_join(string_join("(unknown: ", cast_e2s(e)), " )")
+	elements = dict_keys(dict)
+	while (0 < list_len(elements)):
+		name = set_pop(elements)
+		if (element_eq(dict[name], element)):
+			return name
+
+	return string_join(string_join("(unknown: ", cast_e2s(element)), " )")
 
 String function print_dict(dict : Element):
 	Element keys

+ 1 - 1
integration/code/pn_interface.alc

@@ -405,7 +405,7 @@ Element function initial_prompt():
 			output("Found models:")
 			while (read_nr_out(keys) > 0):
 				m_menu_list = set_pop(keys)
-				output((("  " + m_menu_list) + " : ") + reverseNameLookup(root, root[m_menu_list]["metamodel"]))
+				output((("  " + m_menu_list) + " : ") + reverseKeyLookup(root, root[m_menu_list]["metamodel"]))
 		elif (command == "delete"):
 			output("Model to delete?")
 			name = input()

+ 36 - 12
integration/test_constructors_models.py

@@ -20,6 +20,7 @@ bottom = [
         '"add_node"', 1, '"Type"',
         '"add_node"', 1, '"Any"',
         '"add_node"', 1, '"String"',
+        '"add_node"', 1, '"Integer"',
         '"add_value"', 1, '"inheritance"', '"inheritance"',
         '"add_value"', 1, '"link"', '"link"',
         '"add_value"', 1, '"name"', '"name"',
@@ -43,6 +44,7 @@ retype = [
         '"retype"', 1, '"Type"', '"Class"',
         '"retype"', 1, '"Any"', '"Class"',
         '"retype"', 1, '"String"', '"Type"',
+        '"retype"', 1, '"Integer"', '"Type"',
         '"retype"', 1, '"inheritance"', '"String"',
         '"retype"', 1, '"link"', '"String"',
         '"retype"', 1, '"name"', '"String"',
@@ -58,6 +60,23 @@ retype = [
         '"exit"',
     ]
 
+bottom_attributes = [
+        '"model"',
+        '"instantiate_link"', 1, '"Association"', '"lc"', '"Class"', '"Integer"',
+        '"instantiate_attribute"', 1, '"lc"', '"name"', '"lower_cardinality"',
+        '"instantiate_link"', 1, '"Association"', '"uc"', '"Class"', '"Integer"',
+        '"instantiate_attribute"', 1, '"uc"', '"name"', '"upper_cardinality"',
+        '"instantiate_link"', 1, '"Association"', '"slc"', '"Association"', '"Integer"',
+        '"instantiate_attribute"', 1, '"slc"', '"name"', '"source_lower_cardinality"',
+        '"instantiate_link"', 1, '"Association"', '"suc"', '"Association"', '"Integer"',
+        '"instantiate_attribute"', 1, '"suc"', '"name"', '"source_upper_cardinality"',
+        '"instantiate_link"', 1, '"Association"', '"tlc"', '"Association"', '"Integer"',
+        '"instantiate_attribute"', 1, '"tlc"', '"name"', '"target_lower_cardinality"',
+        '"instantiate_link"', 1, '"Association"', '"tuc"', '"Association"', '"Integer"',
+        '"instantiate_attribute"', 1, '"tuc"', '"name"', '"target_upper_cardinality"',
+        '"exit"',
+    ]
+
 instantiate_scd = [
         '"model"',
         '"instantiate_model"', 1, 2,
@@ -67,9 +86,12 @@ instantiate_scd = [
         '"instantiate_node"', 2, '"Type"', '"Integer"',
         '"instantiate_link"', 2, '"Association"', '"P2T"', '"Place"', '"Transition"',
         '"instantiate_link"', 2, '"Association"', '"T2P"', '"Transition"', '"Place"',
-        '"instantiate_named"', 2, '"Association"', '"tokens"', '"Place"', '"Integer"',
-        '"instantiate_named"', 2, '"Association"', '"weight"', '"P2T"', '"Integer"',
-        '"instantiate_named"', 2, '"Association"', '"weight"', '"T2P"', '"Integer"',
+        '"instantiate_link"', 2, '"Association"', '"Place_tokens"', '"Place"', '"Integer"',
+        '"instantiate_attribute"', 2, '"Place_tokens"', '"name"', '"tokens"',
+        '"instantiate_link"', 2, '"Association"', '"P2T_weight"', '"P2T"', '"Integer"',
+        '"instantiate_attribute"', 2, '"P2T_weight"', '"name"', '"weight"',
+        '"instantiate_link"', 2, '"Association"', '"T2P_weight"', '"T2P"', '"Integer"',
+        '"instantiate_attribute"', 2, '"T2P_weight"', '"name"', '"weight"',
         '"exit"',
     ]
 
@@ -101,8 +123,10 @@ instantiate_example = [
         '"instantiate_node"', 2, '"Class"', '"B"',
         '"instantiate_node"', 2, '"Class"', '"C"',
         '"instantiate_link"', 2, '"Inheritance"', '"b_inherits_a"', '"B"', '"A"',
-        '"instantiate_named"', 2, '"Association"', '"tokens"', '"A"', '"B"',
-        '"instantiate_named"', 2, '"Association"', '"tokens"', '"C"', '"B"',
+        '"instantiate_link"', 2, '"Association"', '"A_tokens"', '"A"', '"B"',
+        '"instantiate_attribute"', 2, '"A_tokens"', '"name"', '"tokens"',
+        '"instantiate_link"', 2, '"Association"', '"C_tokens"', '"C"', '"B"',
+        '"instantiate_attribute"', 2, '"C_tokens"', '"name"', '"tokens"',
         '"exit"',
         '"model"',
         '"instantiate_model"', 2, 3,
@@ -193,37 +217,37 @@ def conformance_check(node):
 
 class TestConstructorsModels(unittest.TestCase):
     def test_constructors_instantiate_bottom(self):
-        commands = bottom + retype + conformance_check(1) + ['"return"', 'false']
+        commands = bottom + retype + bottom_attributes + conformance_check(1) + ['"return"', 'false']
         self.assertTrue(run_barebone(commands, ["OK"], 1))
 
     def test_constructors_instantiate_scd(self):
-        commands = bottom + retype + instantiate_scd + conformance_check(2) + ['"return"', 'false']
+        commands = bottom + retype + bottom_attributes + instantiate_scd + conformance_check(2) + ['"return"', 'false']
         self.assertTrue(run_barebone(commands, ["OK"], 1))
 
     def test_constructors_instantiate_pn(self):
-        commands = bottom + retype + instantiate_scd + instantiate_pn + conformance_check(3) + ['"return"', 'false']
+        commands = bottom + retype + bottom_attributes + instantiate_scd + instantiate_pn + conformance_check(3) + ['"return"', 'false']
         self.assertTrue(run_barebone(commands, ["OK"], 1))
 
     def test_constructors_instantiate_example(self):
-        commands = bottom + retype + instantiate_example + conformance_check(2) + conformance_check(3) + ['"return"', 'false']
+        commands = bottom + retype + bottom_attributes + instantiate_example + conformance_check(2) + conformance_check(3) + ['"return"', 'false']
         self.assertTrue(run_barebone(commands, ["OK", "OK"], 1))
 
     def test_constructors_is_direct_instance(self):
-        commands = bottom + retype + instantiate_example + is_direct_instance + ['"return"', 'false']
+        commands = bottom + retype + bottom_attributes + instantiate_example + is_direct_instance + ['"return"', 'false']
         expected = ['True', 'False', 'False',
                     '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']
+        commands = bottom + retype + bottom_attributes + instantiate_example + is_nominal_instance + ['"return"', 'false']
         expected = ['True', 'True', 'False',
                     'False', 'True', 'False',
                     'False', 'False', 'True']
         self.assertTrue(run_barebone(commands, expected, 1))
 
     def test_constructors_is_structural_instance(self):
-        commands = bottom + retype + instantiate_example + is_structural_instance + ['"return"', 'false']
+        commands = bottom + retype + bottom_attributes + instantiate_example + is_structural_instance + ['"return"', 'false']
         expected = ['True', 'False', 'True',
                     'True', 'True', 'True',
                     'True', 'False', 'True']

+ 21 - 6
integration/utils.py

@@ -180,7 +180,7 @@ def run_file(files, parameters, expected, mode):
             kill(proc)
         except UnboundLocalError:
             pass
-            
+
 def run_barebone(parameters, expected, interface="0", timeout=False, wait=False, link=None, inputs=[]):
     port = getFreePort()
     address = "http://localhost:%i" % port
@@ -192,6 +192,11 @@ def run_barebone(parameters, expected, interface="0", timeout=False, wait=False,
         timeout_val = 15
         start = time.time()
         while 1:
+            proc.poll()
+            if proc.returncode is not None:
+                # Modelverse has already terminated, which isn't a good sign!
+                return False
+
             try:
                 urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": '"%s"' % username, "username": "user_manager"})), timeout=1).read()
                 if interface is not None:
@@ -200,10 +205,6 @@ def run_barebone(parameters, expected, interface="0", timeout=False, wait=False,
             except:
                 time.sleep(0.01)
 
-                if proc.returncode is not None:
-                    # Modelverse has already terminated, which isn't a good sign!
-                    return False
-
                 if time.time() - start > timeout_val:
                     raise
 
@@ -214,12 +215,13 @@ def run_barebone(parameters, expected, interface="0", timeout=False, wait=False,
             if isinstance(p, int):
                 if p not in var_list:
                     data = flush_data(address, data)
-                    val = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username})), timeout=10).read()
 
+                    proc.poll()
                     if proc.returncode is not None:
                         # 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=10).read()
                     val = val.split("=", 2)[1].split("&", 1)[0]
                     var_list[p] = val
                     continue
@@ -246,9 +248,17 @@ def run_barebone(parameters, expected, interface="0", timeout=False, wait=False,
                     kill(proc2)
                     print("Linking timeout expired!")
                     return False
+                if proc.returncode is not None:
+                    # Modelverse has already terminated, which isn't a good sign!
+                    return False
+
 
         for inp in inputs:
             urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": inp, "username": username})), timeout=1).read()
+            proc.poll()
+            if proc.returncode is not None:
+                # Modelverse has already terminated, which isn't a good sign!
+                return False
 
         counter = 0
         for e in expected:
@@ -256,6 +266,11 @@ def run_barebone(parameters, expected, interface="0", timeout=False, wait=False,
             c = len(e) if isinstance(e, set) else 1
             for _ in range(c):
                 try:
+                    proc.poll()
+                    if proc.returncode is not None:
+                        # 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=15).read()
                 except:
                     if timeout:

+ 22 - 7
interface/HUTN/hutn_compiler/linker.py

@@ -1,19 +1,30 @@
 import sys
 import urllib
 import urllib2
+import json
+
+def flush_data(address, data, username):
+    if data:
+        urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "data": json.dumps(data), "username": username})), timeout=10).read()
+    return []
 
 def link(address, username, objects, fast):
     # Read out all symbol tables that are to be linked
     definers = {}
     users = {}
+    data = []
+
     if not fast:
         definers["main"] = None
         for obj in objects:
-            print("[SYMB] %s" % (obj))
-            urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": '3', "username": username}))).read()
-            urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": '"read_symbols"', "username": username}))).read()
-            urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": '"%s"' % obj, "username": username}))).read()
+            data.append(("V", '3'))
+            data.append(("V", '"read_symbols"'))
+            data.append(("V", '"%s"' % obj))
 
+        data = flush_data(address, data, username)
+
+        for obj in objects:
+            print("[SYMB] %s" % (obj))
             v = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username}))).read()
             lst = v.rsplit("=", 1)[1]
             lst = lst.split("\n")
@@ -38,11 +49,15 @@ def link(address, username, objects, fast):
 
     # Ok, we know that all symbols can be defined with this set of files, now link their initializers together
     initializers = []
+    for obj in objects:
+        data.append(("V", '3'))
+        data.append(("V", '"read_initializers"'))
+        data.append(("V", '"%s"' % obj))
+
+    data = flush_data(address, data, username)
+
     for obj in objects:
         print("[LINK] %s" % (obj))
-        urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": '3', "username": username}))).read()
-        urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": '"read_initializers"', "username": username}))).read()
-        urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "element_type": "V", "value": '"%s"' % obj, "username": username}))).read()
         v = urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "username": username}))).read()
         start = str(v.split("&", 1)[0].split("=")[1])
         initializers.append(start)

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

@@ -12,7 +12,6 @@ Element function get_superclasses(model : Element, elem : Element)
 Element function find_attribute_definer(model : Element, elem : Element, name : String)
 Void function instantiate_attribute(model : Element, element : String, attribute_name : String, value : Element)
 String function instantiate_link(model : Element, type : String, name : String, source : String, destination : String)
-Void function instantiate_named(model : Element, type : String, name : String, source : String, destination : String)
 Void function define_inheritance(model : Element, inheritance_name : String)
 Void function unset_attribute(model : Element, elem : String, name : String)
 Void function construct_model()

+ 3 - 3
interface/HUTN/includes/object_operations.alh

@@ -5,7 +5,7 @@ Element function readElementByName(a: Element, b: String)
 Element function getAttributeList(a: Element, b: Element)
 Element function getInstantiatableAttributes(a: Element, b: Element)
 String function getName(a: Element, b: Element)
-String function reverseNameLookup(a: Element, b: Element)
+String function reverseKeyLookup(a: Element, b: Element)
 String function print_dict(dict : Element)
-Element function allPossibleIncoming(model : Element, target : String)
-Element function allPossibleOutgoing(model : Element, source : String)
+Element function selectPossibleIncoming(model : Element, target : String, limit_set : Element)
+Element function selectPossibleOutgoing(model : Element, source : String, limit_set : Element)