浏览代码

Rewrote a lot of model instantiation functions to be more elegant

Yentl Van Tendeloo 9 年之前
父节点
当前提交
8f3b195386
共有 2 个文件被更改,包括 87 次插入28 次删除
  1. 77 19
      bootstrap/modelling.alc
  2. 10 9
      integration/test_constructors_models.py

+ 77 - 19
bootstrap/modelling.alc

@@ -3,7 +3,7 @@ include "io.alh"
 
 String function instantiated_name(element : Element, original : String):
 	if (original == ""):
-		return cast_id2s(element)
+		return "__" + cast_id2s(element)
 	else:
 		return original
 
@@ -89,17 +89,72 @@ String function instantiate_node(model : Element, type_name : String, instance_n
 
 	return actual_name
 
-Void function instantiate_attribute(model : Element, element : String, attribute : String, value : Element):
+Element function find_attribute_type(model : Element, elem : String, name : String):
+	Element mm_elem
+	Element direct_type
+
+	direct_type = dict_read_node(model["type_mapping"], model["model"][elem])
+	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 dict_read_edge(mm_elem, name)
+
+Element function get_superclasses(model : Element, elem : Element):
+	Element result
+	Integer i
+	Integer num_edges
+	Element edge
+
+	// Initialize empty set
+	result = create_node()
+	i = 0
+
+	log(cast_e2s(elem))
+	// Read out all outgoing edges
+	num_edges = read_nr_out(elem)
+	while (i < num_edges):
+		edge = read_out(elem, i)
+		if (element_eq(dict_read_node(model["type_mapping"], edge), model["inheritance"])):
+			create_edge(result, read_edge_dst(edge))
+
+	return result
+
+Element function find_attribute_definer(model : Element, elem : Element, name : String):
+	if (dict_in(elem, name)):
+		// Try in the current class definition
+		log("Found attribute " + name)
+		return elem
+	else:
+		// Not found, so go to all superclasses and try there
+		Element superclasses
+		Element current
+		Element found
+
+		log("Recurse attribute " + name)
+
+		superclasses = get_superclasses(model, elem)
+		while (list_len(superclasses) > 0):
+			current = set_pop(superclasses)
+			found = find_attribute_definer(model, current, name)
+			log("In superclass for " + name)
+			if (bool_not(element_eq(found, read_root()))):
+				// Found something!
+				return current
+
+		// Return the de facto error-value
+		return read_root()
+
+Void function instantiate_attribute(model : Element, element : String, attribute_name : String, value : String):
 	// Instantiate an attribute of something that needs to be instantiated
 	// Actually a bit more difficult than all the rest, as we need to find the attribute to instantiate
-	Element elem
-	Element type
 	Element attr_type
 
-	elem = model["model"][element]
-	type = model["type_mapping"][elem]
-	//attr_type = find_attribute(model, type, attribute)
-	instantiate_link(model, attr_type, "", elem, value)
+	attr_type = find_attribute_type(model, element, attribute_name)
+	instantiate_link(model, attr_type, "", element, value)
 
 	return
 
@@ -112,18 +167,15 @@ String function instantiate_link(model : Element, type : String, name : String,
 
 	return actual_name
 
-Void function instantiate_named_value(model : Element, type : String, name : String, source : String, destination : Element):
-	// Special helper function to create an edge and name it
-	String actual_name
-
-	actual_name = instantiate_link(model, type, "", source, destination)
-	instantiate_attribute(model, model["model"][actual_name], "name", name)
-
-	return
-
 Void function instantiate_named(model : Element, type : String, name : String, source : String, destination : String):
 	// Special helper function to create an edge and name it
-	instantiate_named(model, type, name, source, model["model"][destination])
+	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, model["metamodel"]["model"]["String"])
+	instantiate_attribute(model, link_name, "name", name_name)
 
 	return
 
@@ -155,8 +207,14 @@ Void function construct_model():
 			retype(input(), input(), input())
 		elif (command == "instantiate_model"):
 			output(instantiate_model(input()))
-		elif (command == "instantiate_attribute"):
+		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"):
+			instantiate_link(input(), input(), input(), input(), input())
 		elif (command == "define_inheritance"):
 			define_inheritance(input(), input())
 		else:

+ 10 - 9
integration/test_constructors_models.py

@@ -38,6 +38,7 @@ bottom = [
 retype = [
         '"model"', 
         '"retype_model"', 1, 1,
+        '"define_inheritance"', 1, '"l3"',
         '"retype"', 1, '"Class"', '"Class"',
         '"retype"', 1, '"Type"', '"Class"',
         '"retype"', 1, '"Any"', '"Class"',
@@ -54,21 +55,21 @@ retype = [
         '"retype"', 1, '"l7"', '"l8"',
         '"retype"', 1, '"l8"', '"l5"',
         '"retype"', 1, '"l9"', '"l8"',
-        '"define_inheritance"', 1, '"l3"',
         '"exit"',
     ]
 
 instantiate_pn = [
         '"model"',
         '"instantiate_model"', 1, 2,
-        '"instantiate_node"', 1, '"Class"', '"Place"',
-        '"instantiate_node"', 1, '"Class"', '"Transition"',
-        '"instantiate_node"', 1, '"Type"', '"Integer"',
-        '"instantiate_named"', 1, '"l5"', '"P2T"', '"Place"', '"Transition"',
-        '"instantiate_named"', 1, '"l5"', '"T2P"', '"Transition"', '"Place"',
-        '"instantiate_named"', 1, '"l5"', '"tokens"', '"Place"', '"Integer"',
-        '"instantiate_named"', 1, '"l5"', '"weight"', '"P2T"', '"Integer"',
-        '"instantiate_named"', 1, '"l5"', '"weight"', '"T2P"', '"Integer"',
+        '"define_inheritance"', 2, '"l3"',
+        '"instantiate_node"', 2, '"Class"', '"Place"',
+        '"instantiate_node"', 2, '"Class"', '"Transition"',
+        '"instantiate_node"', 2, '"Type"', '"Integer"',
+        '"instantiate_link"', 2, '"l5"', '"P2T"', '"Place"', '"Transition"',
+        '"instantiate_link"', 2, '"l5"', '"T2P"', '"Transition"', '"Place"',
+        '"instantiate_named"', 2, '"l5"', '"tokens"', '"Place"', '"Integer"',
+        '"instantiate_named"', 2, '"l5"', '"weight"', '"P2T"', '"Integer"',
+        '"instantiate_named"', 2, '"l5"', '"weight"', '"T2P"', '"Integer"',
         '"exit"',
     ]