浏览代码

Updated model transformation algorithm searching for applicable nodes

Yentl Van Tendeloo 8 年之前
父节点
当前提交
df892a9515
共有 2 个文件被更改,包括 105 次插入91 次删除
  1. 58 58
      bootstrap/constructors.alc
  2. 47 33
      bootstrap/transform.alc

+ 58 - 58
bootstrap/constructors.alc

@@ -27,37 +27,37 @@ Action function construct_global():
 
 	this_element = create_value(!global)
 	declared_element = input()
-	dict_add(this_element, "var", declared_element)
+	dict_add_fast(this_element, "var", declared_element)
 
 	// Defines
 	Action assign
 	Action resolve
 	Action value
 	assign = create_value(!assign)
-	dict_add(this_element, "next", assign)
+	dict_add_fast(this_element, "next", assign)
 	resolve = create_value(!resolve)
-	dict_add(assign, "var", resolve)
-	dict_add(resolve, "var", declared_element)
+	dict_add_fast(assign, "var", resolve)
+	dict_add_fast(resolve, "var", declared_element)
 	op = input()
 	if (op == "deref"):
 		value = create_value(!constant)
-		dict_add(value, "node", import_node(input()))
+		dict_add_fast(value, "node", import_node(input()))
 	elif (op == "empty"):
 		value = create_value(!call)
 		Element res
 		Element acc
 		res = create_value(!resolve)
 		acc = create_value(!access)
-		dict_add(value, "func", acc)
-		dict_add(acc, "var", res)
-		dict_add(res, "var", "create_node")
+		dict_add_fast(value, "func", acc)
+		dict_add_fast(acc, "var", res)
+		dict_add_fast(res, "var", "create_node")
 	elif (op == "const"):
 		value = create_value(!constant)
-		dict_add(value, "node", input())
-	dict_add(assign, "value", value)
+		dict_add_fast(value, "node", input())
+	dict_add_fast(assign, "value", value)
 
 	if (input()):
-		dict_add(assign, "next", construct_top())
+		dict_add_fast(assign, "next", construct_top())
 	return this_element!
 
 Action function construct_top_funcdef(mutable : Boolean):
@@ -81,16 +81,16 @@ Action function construct_top_funcdef(mutable : Boolean):
 		formal = name
 	func = create_node()
 	params = create_node()
-	dict_add(global, "var", formal)
-	dict_add(global, "next", assign)
-	dict_add(assign, "var", resolve)
-	dict_add(assign, "value", constant)
-	dict_add(resolve, "var", formal)
-	dict_add(constant, "node", func)
-	dict_add(func, "params", params)
+	dict_add_fast(global, "var", formal)
+	dict_add_fast(global, "next", assign)
+	dict_add_fast(assign, "var", resolve)
+	dict_add_fast(assign, "value", constant)
+	dict_add_fast(resolve, "var", formal)
+	dict_add_fast(constant, "node", func)
+	dict_add_fast(func, "params", params)
 
 	if (mutable):
-		dict_add(func, "mutable", create_node())
+		dict_add_fast(func, "mutable", create_node())
 
 	Integer nrParams
 	nrParams = input()
@@ -103,17 +103,17 @@ Action function construct_top_funcdef(mutable : Boolean):
 
 	while (counter < nrParams):
 		param = create_node()
-		dict_add(params, string_get(arg_names_decl, counter), param)
-		dict_add(param, "name", string_get(arg_names_decl, counter))
-		dict_add(variable_map, input(), param)
+		dict_add_fast(params, string_get(arg_names_decl, counter), param)
+		dict_add_fast(param, "name", string_get(arg_names_decl, counter))
+		dict_add_fast(variable_map, input(), param)
 		// Output each parameter in turn
 		counter = counter + 1
 
 	// Now add the body
-	dict_add(func, "body", construct_unknown())
+	dict_add_fast(func, "body", construct_unknown())
 
 	if (input()):
-		dict_add(assign, "next", construct_top())
+		dict_add_fast(assign, "next", construct_top())
 
 	return global!
 
@@ -160,31 +160,31 @@ Action function construct_unknown():
 Action function construct_if():
 	Action this_element
 	this_element = create_value(!if)
-	dict_add(this_element, "cond", construct_unknown())
-	dict_add(this_element, "then", construct_unknown())
+	dict_add_fast(this_element, "cond", construct_unknown())
+	dict_add_fast(this_element, "then", construct_unknown())
 	if (input()):
-		dict_add(this_element, "else", construct_unknown())
+		dict_add_fast(this_element, "else", construct_unknown())
 	if (input()):
-		dict_add(this_element, "next", construct_unknown())
+		dict_add_fast(this_element, "next", construct_unknown())
 	return this_element!
 
 Action function construct_while():
 	Action this_element
 	this_element = create_value(!while)
-	dict_add(this_element, "cond", construct_unknown())
+	dict_add_fast(this_element, "cond", construct_unknown())
 
 	list_append(while_stack, this_element)
-	dict_add(this_element, "body", construct_unknown())
+	dict_add_fast(this_element, "body", construct_unknown())
 	list_delete(while_stack, list_len(while_stack) - 1)
 
 	if (input()):
-		dict_add(this_element, "next", construct_unknown())
+		dict_add_fast(this_element, "next", construct_unknown())
 	return this_element!
 
 Action function construct_access():
 	Action this_element
 	this_element = create_value(!access)
-	dict_add(this_element, "var", construct_unknown())
+	dict_add_fast(this_element, "var", construct_unknown())
 	return this_element!
 
 Action function construct_resolve():
@@ -198,22 +198,22 @@ Action function construct_resolve():
 		linked_element = variable_map[name]
 	else:
 		linked_element = name
-	dict_add(this_element, "var", linked_element)
+	dict_add_fast(this_element, "var", linked_element)
 	return this_element!
 
 Action function construct_assign():
 	Action this_element
 	this_element = create_value(!assign)
-	dict_add(this_element, "var", construct_unknown())
-	dict_add(this_element, "value", construct_unknown())
+	dict_add_fast(this_element, "var", construct_unknown())
+	dict_add_fast(this_element, "value", construct_unknown())
 	if (input()):
-		dict_add(this_element, "next", construct_unknown())
+		dict_add_fast(this_element, "next", construct_unknown())
 	return this_element!
 
 Action function construct_call():
 	Action this_element
 	this_element = create_value(!call)
-	dict_add(this_element, "func", construct_unknown())
+	dict_add_fast(this_element, "func", construct_unknown())
 
 	Integer nrParams
 	nrParams = input()
@@ -228,29 +228,29 @@ Action function construct_call():
 	while (counter < nrParams):
 		param = create_node()
 
-		dict_add(param, "name", string_get(arg_names_call, counter))
-		dict_add(param, "value", construct_unknown())
+		dict_add_fast(param, "name", string_get(arg_names_call, counter))
+		dict_add_fast(param, "value", construct_unknown())
 
 		if (counter == 0):
-			dict_add(this_element, "params", param)
+			dict_add_fast(this_element, "params", param)
 		else:
-			dict_add(prev_param, "next_param", param)
+			dict_add_fast(prev_param, "next_param", param)
 		prev_param = param
 
 		counter = counter + 1
 
 	if (nrParams > 0):
-		dict_add(this_element, "last_param", prev_param)
+		dict_add_fast(this_element, "last_param", prev_param)
 
 	if (input()):
-		dict_add(this_element, "next", construct_unknown())
+		dict_add_fast(this_element, "next", construct_unknown())
 	return this_element!
 
 Action function construct_return():
 	if (input()):
 		Action this_element
 		this_element = create_value(!return)
-		dict_add(this_element, "value", construct_unknown())
+		dict_add_fast(this_element, "value", construct_unknown())
 		return this_element!
 	else:
 		return create_value(!return)!
@@ -258,7 +258,7 @@ Action function construct_return():
 Action function construct_const():
 	Action this_element
 	this_element = create_value(!constant)
-	dict_add(this_element, "node", input())
+	dict_add_fast(this_element, "node", input())
 	return this_element!
 
 Action function construct_declare():
@@ -268,11 +268,11 @@ Action function construct_declare():
 
 	this_element = create_value(!declare)
 	declared_element = create_node()
-	dict_add(this_element, "var", declared_element)
+	dict_add_fast(this_element, "var", declared_element)
 	name = input()
-	dict_add(variable_map, name, declared_element)
+	dict_add_fast(variable_map, name, declared_element)
 	if (input()):
-		dict_add(this_element, "next", construct_unknown())
+		dict_add_fast(this_element, "next", construct_unknown())
 	return this_element!
 
 Action function construct_input():
@@ -283,27 +283,27 @@ Action function construct_input():
 Action function construct_output():
 	Action this_element
 	this_element = create_value(!output)
-	dict_add(this_element, "value", construct_unknown())
+	dict_add_fast(this_element, "value", construct_unknown())
 	if (input()):
-		dict_add(this_element, "next", construct_unknown())
+		dict_add_fast(this_element, "next", construct_unknown())
 	return this_element!
 
 Action function construct_deref():
 	Action this_element
 	this_element = create_value(!constant)
-	dict_add(this_element, "node", import_node(input()))
+	dict_add_fast(this_element, "node", import_node(input()))
 	return this_element!
 
 Action function construct_break():
 	Action this_element
 	this_element = create_value(!break)
-	dict_add(this_element, "while", while_stack[list_len(while_stack) - 1])
+	dict_add_fast(this_element, "while", while_stack[list_len(while_stack) - 1])
 	return this_element!
 
 Action function construct_continue():
 	Action this_element
 	this_element = create_value(!continue)
-	dict_add(this_element, "while", while_stack[list_len(while_stack) - 1])
+	dict_add_fast(this_element, "while", while_stack[list_len(while_stack) - 1])
 	return this_element!
 
 Action function construct_function():
@@ -330,20 +330,20 @@ Action function construct_function():
 	counter = 0
 	func = create_node()
 	arg_names_decl = "abcdefghijklmnopqrstuvwxyz"
-	dict_add(func, "params", params)
+	dict_add_fast(func, "params", params)
 
 	if (inp == "mutable_funcdef"):
-		dict_add(func, "mutable", create_node())
+		dict_add_fast(func, "mutable", create_node())
 
 	while (counter < nrParams):
 		param = create_node()
-		dict_add(params, string_get(arg_names_decl, counter), param)
-		dict_add(variable_map, input(), param)
+		dict_add_fast(params, string_get(arg_names_decl, counter), param)
+		dict_add_fast(variable_map, input(), param)
 		// Output each parameter in turn
 		counter = counter + 1
 
 	// Now add the body
-	dict_add(func, "body", construct_unknown())
+	dict_add_fast(func, "body", construct_unknown())
 
 	// Consume the final 'false', to indicate that no additional code will come
 	input()

+ 47 - 33
bootstrap/transform.alc

@@ -77,53 +77,50 @@ Element function get_possible_bindings(host_model : Element, schedule_model : El
 	String dst_label
 	String typename
 	String original_typename
+	Boolean guaranteed_instance
 
 	options = create_node()
 
 	typename = read_type(schedule_model, current_element)
 	original_typename = string_substr(typename, 4, string_len(typename))
+	guaranteed_instance = False
 	
 	if (is_edge(schedule_model["model"][current_element])):
+		Boolean src_in
+		Boolean dst_in
 		// Is an edge, so check for already bound source/target
 		src_label = read_attribute(schedule_model, reverseKeyLookup(schedule_model["model"], read_edge_src(schedule_model["model"][current_element])), "label")
 		dst_label = read_attribute(schedule_model, reverseKeyLookup(schedule_model["model"], read_edge_dst(schedule_model["model"][current_element])), "label")
+		src_in = set_in(dict_keys(map), src_label)
+		dst_in = set_in(dict_keys(map), dst_label)
 
-		if (bool_and(set_in(dict_keys(map), src_label), set_in(dict_keys(map), dst_label))):
+		guaranteed_instance = True
+
+		if (bool_and(src_in, dst_in)):
 			// Source and destination are bound
 			options = allOutgoingAssociationInstances(host_model, map[src_label], original_typename)
-			options = set_overlap(options, allIncomingAssociationInstances(host_model, map[dst_label], original_typename))
+			if (read_nr_out(options) > 0):
+				options = set_overlap(options, allIncomingAssociationInstances(host_model, map[dst_label], original_typename))
 
-		elif (set_in(dict_keys(map), src_label)):
+		elif (src_in):
 			// Source is bound
 			options = allOutgoingAssociationInstances(host_model, map[src_label], original_typename)
 
-		elif (set_in(dict_keys(map), dst_label)):
+		elif (dst_in):
 			// Destination is bound
 			options = allIncomingAssociationInstances(host_model, map[dst_label], original_typename)
 
 		else:
 			// Neither is bound, so just get all of them
-			return allInstances(host_model, original_typename)!
+			options = allInstances(host_model, original_typename)
 	else:
 		// Is a node, so find whether or not there are some connections that are already resolved
 		Element ic
 		Element oc
 		String poll
+		String value
 
-		// TODO optimize: do outgoing first, and only get incoming when not yet failed for incoming (incoming much slower!)
-
-		ic = allIncomingAssociationInstances(schedule_model, current_element, "PreElement")
 		oc = allOutgoingAssociationInstances(schedule_model, current_element, "PreElement")
-
-		String value
-		while (bool_and(read_nr_out(ic) > 0, read_nr_out(options) < 2)):
-			poll = set_pop(ic)
-			if (dict_in(map, read_attribute(schedule_model, poll, "label"))):
-				// This incoming link is already defined, so we just have one option: the destination of the link we matched
-				value = readAssociationDestination(host_model, map[read_attribute(schedule_model, poll, "label")])
-				if (bool_not(set_in(options, value))):
-					set_add(options, value)
-			
 		while (bool_and(read_nr_out(oc) > 0, read_nr_out(options) < 2)):
 			poll = set_pop(oc)
 			if (dict_in(map, read_attribute(schedule_model, poll, "label"))):
@@ -132,9 +129,22 @@ Element function get_possible_bindings(host_model : Element, schedule_model : El
 				if (bool_not(set_in(options, value))):
 					set_add(options, value)
 
+		if (read_nr_out(options) < 2):
+			ic = allIncomingAssociationInstances(schedule_model, current_element, "PreElement")
+			String value
+			while (bool_and(read_nr_out(ic) > 0, read_nr_out(options) < 2)):
+				poll = set_pop(ic)
+				if (dict_in(map, read_attribute(schedule_model, poll, "label"))):
+					// This incoming link is already defined, so we just have one option: the destination of the link we matched
+					value = readAssociationDestination(host_model, map[read_attribute(schedule_model, poll, "label")])
+					if (bool_not(set_in(options, value))):
+						set_add(options, value)
+			
 		if (read_nr_out(options) == 0):
 			// Is a node and no connections, so we just pick all options
 			options = allInstances(host_model, original_typename)
+			guaranteed_instance = True
+
 		elif (read_nr_out(options) > 1):
 			// Multiple "only" options, which will not work out: no options!
 			return create_node()!
@@ -152,23 +162,27 @@ Element function get_possible_bindings(host_model : Element, schedule_model : El
 			// Option is already present with another label, so skip this!
 
 			// Check if it conforms to the desired type
-			if (is_nominal_instance(host_model, option, original_typename)):
-				// Check for local constraints of element
-				if (element_eq(read_attribute(schedule_model, current_element, "constraint"), read_root())):
-					// No local constraints, so all is well
-					set_add(filtered_options, option)
-				else:
-					// Check local constraints and add only if positive
-					Element constraint_function
-					Boolean result
-					Element func
+			if (bool_not(guaranteed_instance)):
+				if (bool_not(is_nominal_instance(host_model, option, original_typename))):
+					// Not an actual instance, so skip!
+					continue!
+
+			// Check for local (matching) constraints of element
+			if (element_eq(read_attribute(schedule_model, current_element, "constraint"), read_root())):
+				// No local constraints, so all is well
+				set_add(filtered_options, option)
+			else:
+				// Check local constraints and add only if positive
+				Element constraint_function
+				Boolean result
+				Element func
 
-					constraint_function = read_attribute(schedule_model, current_element, "constraint")
-					func = get_func_AL_model(import_node(constraint_function))
-					result = func(host_model, option)
+				constraint_function = read_attribute(schedule_model, current_element, "constraint")
+				func = get_func_AL_model(import_node(constraint_function))
+				result = func(host_model, option)
 
-					if (result):
-						set_add(filtered_options, option)
+				if (result):
+					set_add(filtered_options, option)
 
 	Element attributes
 	String attribute