Browse Source

Added new constructor for constraints (anonymous function)

Yentl Van Tendeloo 9 years ago
parent
commit
ae9a592153

+ 28 - 0
bootstrap/conformance_scd.alc

@@ -168,6 +168,15 @@ String function conformance_scd(model : Element):
 							if (integer_lt(cardinalities[check_type]["suc"], instances)):
 								return "Upper cardinality violation for incoming edge at " + model_name
 
+			Element constraint_function
+			constraint_function = read_attribute(model, model_name, "constraint")
+			if (element_neq(constraint_function, read_root())):
+				String result
+				// TODO define the local_constraint execution function
+				result = execute_local_constraint(model, model_name)
+				if (result != "OK"):
+					return result
+
 	// Check multiplicities, if they are defined (optional)
 	Element metamodel_keys
 	String metamodel_element
@@ -225,3 +234,22 @@ Element function generate_bottom_type_mapping(model : Element):
 			dict_add(tm, elem, mm["Node"])
 
 	return model
+
+String function execute_local_constraint(model : Element, element : String):
+	Element action
+	Element params
+	Element param
+	Element second_param
+
+	action = read_attribute(model, element, "constraint")
+	params = create_node()
+	param = create_node()
+	dict_add(param, "name", "a")
+	dict_add(param, "value", model)
+	second_param = create_node()
+	dict_add(second_param, "name", "b")
+	dict_add(second_param, "value", element)
+	dict_add(param, "next_param", second_param)
+	dict_add(params, "params", param)
+	dict_add(params, "last_param", second_param)
+	return eval(action, params)

+ 28 - 2
bootstrap/constructors.alc

@@ -120,8 +120,6 @@ Action function construct_unknown():
 		return construct_const()
 	elif (elem == "declare"):
 		return construct_declare()
-	elif (elem == "funcdef"):
-		return construct_funcdef()
 	elif (elem == "output"):
 		return construct_output()
 	elif (elem == "input"):
@@ -136,6 +134,8 @@ Action function construct_unknown():
 		construct_model()
 		log("Constructed model")
 		return construct_unknown()
+	elif (elem == "fundef"):
+		return construct_funcdef()
 	else:
 		log("ERROR: did not understand command " + cast_e2s(elem))
 
@@ -318,3 +318,29 @@ Action function construct_continue():
 	this_element = create_value(!continue)
 	dict_add(this_element, "while", while_stack[list_len(while_stack) - 1])
 	return this_element
+
+Action function construct_function():
+	Action func
+	Integer nrParams
+	Integer counter
+	Element param
+	Element params
+	String arg_names_decl
+
+	params = create_node()
+	nrParams = input()
+	counter = 0
+	func = create_node()
+	arg_names_decl = "abcdefghijklmnopqrstuvwxyz"
+
+	while (counter < nrParams):
+		param = create_node()
+		dict_add(params, string_get(arg_names_decl, counter), param)
+		output(param)
+		// Output each parameter in turn
+		counter = counter + 1
+
+	// Now add the body
+	dict_add(func, "body", construct_unknown())
+
+	return func

+ 53 - 0
bootstrap/modelling.alc

@@ -233,6 +233,57 @@ Void function unset_attribute(model : Element, element : String, attribute : Str
 
 	return
 
+Void function recursive_add_AL(model : Element, element : Element):
+	// TODO
+	String name
+
+	name = "__" + cast_id2s(element)
+	if (dict_in(model["model"], name)):
+		return
+	else:
+		// Add this element and call it for all its outgoing links
+		dict_add(model["model"], name, element)
+		if (is_physical_action(element)):
+			dict_add(model["type_mapping"], element, model["metamodel"][cast_a2s(element)])
+		else:
+			// Either dealing with a param, a funcdef, or just some other kind of node that we have no clue about
+			// TODO add this code
+			return
+
+		// Add all its outgoing links
+		Integer counter
+		Integer i
+		Element elem
+
+		counter = read_nr_out(element)
+		i = 0
+		while (i < counter):
+			elem = read_out(element, i)
+			// TODO add the link and all its attributes
+
+			recursive_add_AL(model, elem)
+			i = i + 1
+
+		return
+
+String function type_action_code(model : Element, constraint : Action):
+	recursive_add_AL(model, constraint)
+	return reverseKeyLookup(model["model"], constraint)
+
+Void function add_constraint(model : Element, element : String):
+	// Add local constraints to an element
+	Action constraint
+	Element attr_type
+	String link_name
+	String constraint_name
+
+	constraint = construct_function()
+	attr_type = find_attribute_type(model, element, "constraint")
+	constraint_name = type_action_code(model, constraint)
+	link_name = instantiate_link(model, attr_type, "", model["model"][element], constraint_name)
+
+	return
+
 Void function construct_model():
 	String command
 	while (True):
@@ -261,5 +312,7 @@ Void function construct_model():
 			instantiate_link(input(), input(), input(), input(), input())
 		elif (command == "define_inheritance"):
 			define_inheritance(input(), input())
+		elif (command == "add_constraint"):
+			add_constraint(input(), input())
 		else:
 			log("Modelling error: did not understand command " + command)

+ 24 - 1
bootstrap/primitives.alc

@@ -104,6 +104,30 @@ Element function exec(first_instr : Element):
 
 	return n()
 
+Element function eval(funcdef : Element, params : Element):
+	// This does some even more ugly things, so don't touch this unless you know what you are doing!
+	Action ret_value
+	Action call
+	Action cons_value
+	Element n
+
+	ret_value = create_value(!return)
+	call = create_value(!call)
+	cons_value = create_value(!constant)
+	n = create_node()
+
+	dict_add(n, "params", create_node())
+	dict_add(n, "body", ret_value)
+	dict_add(ret_value, "value", call)
+	dict_add(call, "func", cons_value)
+	dict_add(cons_value, "node", funcdef)
+
+	if (list_len(params) > 0):
+		dict_add(call, "params", params["params"])
+		dict_add(call, "last_param", params["last_param"])
+
+	return n()
+
 Boolean function string_startswith(a: String, b: String):
 	Integer i
 	i = 0
@@ -132,7 +156,6 @@ Boolean function integer_lte(a: Integer, b: Integer):
 Boolean function integer_gte(a: Integer, b: Integer):
 	return bool_or(integer_gt(a, b), value_eq(a, b))
 
-// TODO: implement these explicitly and split off this code from the primitives completely
 String function string_substr(a: String, b: Integer, c: Integer):
 	String result
 	Integer i

+ 31 - 3
integration/test_constructors_models.py

@@ -81,9 +81,12 @@ action_language = [
         '"instantiate_node"', 1, '"Class"', '"Input"',
         '"instantiate_node"', 1, '"Class"', '"Resolve"',
         '"instantiate_node"', 1, '"Class"', '"Call"',
-        '"instantiate_link"', 1, '"Inheritance"', '""', '"Funcdef"', '"Any"',
+        '"instantiate_link"', 1, '"Association"', '"dict_link"', '"Action"', '"Action"',
+        '"instantiate_link"', 1, '"Association"', '"to_str"', '"dict_link"', '"String"',
+        '"instantiate_attribute"', 1, '"to_str"', '"name"', '"name"',
         '"instantiate_link"', 1, '"Inheritance"', '""', '"Action"', '"Any"',
-        '"instantiate_link"', 1, '"Inheritance"', '""', '"Param"', '"Any"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"Funcdef"', '"Action"',
+        '"instantiate_link"', 1, '"Inheritance"', '""', '"Param"', '"Action"',
         '"instantiate_link"', 1, '"Inheritance"', '""', '"Statement"', '"Action"',
         '"instantiate_link"', 1, '"Inheritance"', '""', '"Expression"', '"Action"',
         '"instantiate_link"', 1, '"Inheritance"', '""', '"Resolve"', '"Statement"',
@@ -163,6 +166,31 @@ bottom_attributes = [
         '"instantiate_attribute"', 1, '"tlc"', '"name"', '"target_lower_cardinality"',
         '"instantiate_link"', 1, '"Association"', '"tuc"', '"Association"', '"Integer"',
         '"instantiate_attribute"', 1, '"tuc"', '"name"', '"target_upper_cardinality"',
+        '"instantiate_link"', 1, '"Association"', '"constraint"', '"Any"', '"Funcdef"',
+        '"instantiate_attribute"', 1, '"constraint"', '"name"', '"constraint"',
+        '"exit"',
+    ]
+
+add_constraints = [
+        '"model"',
+        '"add_constraint"', 1, '"Integer"',
+            '2', 10, 11,
+                '"return"', 'true',
+                    '"call"',
+                        '"access"', '"resolve"', '"is_physical_int"',
+                        '1',
+                        '"call"',
+                            '"access"', '"resolve"', '"dict_read"',
+                            '2',
+                            '"call"',
+                                '"access"', '"resolve"', '"dict_read"',
+                                '2',
+                                '"const"', 10,
+                                '"const"', '"model"',
+                                'false',
+                            '"const"', 11,
+                            'false',
+                        'false',
         '"exit"',
     ]
 
@@ -279,7 +307,7 @@ class TestConstructorsModels(unittest.TestCase):
         self.assertTrue(run_barebone(commands, ["OK"], 1))
 
     def test_constructors_action_language(self):
-        commands = bottom + retype + bottom_attributes + action_language + conformance_check(1) + ['"return"', 'false']
+        commands = bottom + retype + action_language + bottom_attributes + conformance_check(1) + ['"return"', 'false']
         self.assertTrue(run_barebone(commands, ["OK"], 1))
 
     def test_constructors_instantiate_scd(self):

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

@@ -1,2 +1,3 @@
 Action function construct_top()
 Action function construct_unknown()
+Action function construct_function()