Explorar o código

Merge branch 'yentl' into new-sccd

Yentl Van Tendeloo %!s(int64=9) %!d(string=hai) anos
pai
achega
293c05b691

+ 52 - 0
bootstrap/conformance_scd.alc

@@ -19,6 +19,7 @@ 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)):
@@ -80,6 +81,8 @@ String function conformance_scd(model : Element):
 	Element src_metamodel
 	Element dst_metamodel
 	Element element
+	Element check_list
+	Element check_type
 
 	// Load in variables
 	keys = dict_keys(model["model"])
@@ -112,6 +115,55 @@ 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
+		check_list = allPossibleIncoming(model, model_name)
+		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
+
+		// Identical, but for outgoing, and thus for A in the figure
+		check_list = allPossibleOutgoing(model, model_name)
+		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
+
 	// Check multiplicities, if they are defined (optional)
 	Element metamodel_keys
 	String metamodel_element

+ 51 - 4
bootstrap/metamodels.alc

@@ -25,12 +25,32 @@ Element function create_metamodels():
 		model_add_edge(scd, "association_attr", "Association", "String")
 		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_value(scd, "upper_multiplicity", "upper_multiplicity")
 		model_add_edge(scd, "class_to_lm", "Class", "Integer")
-		model_add_edge(scd, "class_to_um", "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")
@@ -51,12 +71,39 @@ 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, "class_to_um", "Association")
-		retype(scd, "lm_name", "association_attr")
 		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")
 
 		export_node("models/SimpleClassDiagrams", scd)
 

+ 0 - 2
bootstrap/modelling.alc

@@ -118,7 +118,6 @@ Element function get_superclasses(model : Element, elem : Element):
 	num_edges = read_nr_out(elem)
 	log(cast_i2s(num_edges))
 	while (i < num_edges):
-		log("Search SC")
 		edge = read_out(elem, i)
 		log(cast_e2s(edge))
 		if (element_eq(dict_read_node(model["type_mapping"], edge), model["inheritance"])):
@@ -139,7 +138,6 @@ Element function find_attribute_definer(model : Element, elem : Element, name :
 
 		superclasses = get_superclasses(model, elem)
 		while (list_len(superclasses) > 0):
-			log("Search")
 			current = set_pop(superclasses)
 			found = find_attribute_definer(model, current, name)
 			if (bool_not(element_eq(found, read_root()))):

+ 44 - 0
bootstrap/object_operations.alc

@@ -25,6 +25,50 @@ Element function allInstances(model : Element, type : Element):
 	
 	return result
 
+Element function allPossibleIncoming(model : Element, target : String):
+	// 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
+	Element result
+
+	result = create_node()
+	metamodel = model["metamodel"]
+	all_elems = dict_keys(metamodel["model"])
+	
+	while (0 < list_len(all_elems)):
+		type = set_pop(all_elems)
+		elem = metamodel["model"][type]
+		if (is_edge(elem)):
+			if (is_nominal_instance(model, model["model"][target], read_edge_src(elem))):
+				set_add(result, elem)
+	
+	return result
+
+Element function allPossibleOutgoing(model : Element, source : String):
+	// 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
+	Element result
+
+	result = create_node()
+	metamodel = model["metamodel"]
+	all_elems = dict_keys(model["metamodel"]["model"])
+	
+	while (0 < list_len(all_elems)):
+		type = set_pop(all_elems)
+		elem = metamodel["model"][type]
+		if (is_edge(elem)):
+			if (is_nominal_instance(model, model["model"][source], read_edge_dst(elem))):
+				set_add(result, elem)
+	
+	return result
+
 Element function allOutgoingAssociationInstances(model : Element, source : Element, assoc : Element):
 	// Read out all outgoing edges of the model and select those that are typed by the specified association
 	// TODO for some reason this crashes if allInstances is used!

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

@@ -7,3 +7,5 @@ Element function getInstantiatableAttributes(a: Element, b: Element)
 String function getName(a: Element, b: Element)
 String function reverseNameLookup(a: Element, b: Element)
 String function print_dict(dict : Element)
+Element function allPossibleIncoming(model : Element, target : String)
+Element function allPossibleOutgoing(model : Element, source : String)

+ 2 - 2
scripts/compile.py

@@ -3,11 +3,11 @@ import os
 import urllib2
 import subprocess
 
-def do_compile(address, filename, username, modulename, mode):
+def do_compile(address, filename, username, modulename, mode, optionals=[]):
     filename = os.path.realpath(filename)
     try:
         urllib2.urlopen(urllib2.Request(address, 'op=set_input&username=user_manager&element_type=V&value="%s"' % username)).read()
-        subprocess.check_call([sys.executable, "hutn_compiler/compiler.py", filename, "grammars/actionlanguage.g", mode, username, modulename, filename, address], cwd="interface/HUTN")
+        subprocess.check_call([sys.executable, "hutn_compiler/compiler.py", filename, "grammars/actionlanguage.g", mode, username, modulename, filename, address] + optionals, cwd="interface/HUTN")
     except urllib2.URLError:
         return 2
     except:

+ 1 - 1
scripts/make_parallel.py

@@ -16,7 +16,7 @@ username = sys.argv[2]
 files = [a.replace("\\", "/") for a in sum([glob.glob(f) for f in sys.argv[3:]], [])]
 
 def do_compile_wrapper(filename):
-    do_compile(address, filename, str(random.random()), filename, "PO")
+    do_compile(address, filename, str(random.random()), filename, "PO", ["--debug"])
 
 if __name__ == "__main__":
     p = multiprocessing.Pool(multiprocessing.cpu_count())