瀏覽代碼

Merge remote-tracking branch 'yentl/testing' into jit

jonathanvdc 8 年之前
父節點
當前提交
025b346d2c
共有 48 個文件被更改,包括 1192 次插入1390 次删除
  1. 62 2
      bootstrap/conformance_scd.alc
  2. 143 250
      bootstrap/metamodels.alc
  3. 104 45
      bootstrap/modelling.alc
  4. 14 9
      bootstrap/object_operations.alc
  5. 102 100
      bootstrap/ramify.alc
  6. 92 25
      bootstrap/transform.alc
  7. 12 3
      core/core_algorithm.alc
  8. 52 45
      core/core_formalism.mvc
  9. 38 36
      core/mini_modify.alc
  10. 18 22
      integration/code/cbd_design.mvc
  11. 23 43
      integration/code/cbd_runtime.mvc
  12. 11 19
      integration/code/fsa_design.mvc
  13. 11 19
      integration/code/fsa_runtime.mvc
  14. 1 2
      integration/code/my_petrinet_with_MM.mvc
  15. 14 9
      integration/code/my_petrinet_with_MM_and_constraints.mvc
  16. 2 1
      integration/code/petrinets.mvc
  17. 18 9
      integration/code/petrinets_constraints.mvc
  18. 2 2
      integration/code/pn_design.mvc
  19. 18 25
      integration/code/pn_design_to_runtime.mvc
  20. 4 4
      integration/code/pn_print.mvc
  21. 0 27
      integration/code/pn_print_MR.mvc
  22. 3 3
      integration/code/pn_runtime.mvc
  23. 0 19
      integration/code/pn_runtime_MR.mvc
  24. 0 26
      integration/code/pn_runtime_model_MR.mvc
  25. 15 19
      integration/code/pn_runtime_to_design.mvc
  26. 23 62
      integration/code/pn_simulate.mvc
  27. 5 17
      integration/code/ramified_petrinets.mvc
  28. 0 127
      integration/code/rpgame.mvc
  29. 0 97
      integration/code/rpgame_semantics.alc
  30. 19 21
      integration/code/several_petrinets.mvc
  31. 22 12
      integration/code/simpleclassdiagrams.mvc
  32. 318 245
      integration/test_constructors_models.py
  33. 1 1
      integration/test_constructors_models_compiled.py
  34. 9 0
      integration/utils.py
  35. 3 3
      interface/HUTN/grammars/modelling.g
  36. 5 20
      interface/HUTN/hutn_compiler/model_visitor.py
  37. 6 1
      interface/HUTN/includes/metamodels.alh
  38. 2 2
      interface/HUTN/includes/modelling.alh
  39. 1 1
      interface/HUTN/test/modelling_language/code/my_petrinet_with_MM.mvc
  40. 1 1
      interface/HUTN/test/modelling_language/code/petrinets.mvc
  41. 10 9
      interface/HUTN/test/modelling_language/code/petrinets_constraints.mvc
  42. 2 2
      interface/HUTN/test/modelling_language/code/simpleclassdiagrams.mvc
  43. 1 1
      interface/HUTN/test/modelling_language/expected/my_petrinet
  44. 1 1
      interface/HUTN/test/modelling_language/expected/my_petrinet_with_MM
  45. 1 1
      interface/HUTN/test/modelling_language/expected/petrinets
  46. 1 1
      interface/HUTN/test/modelling_language/expected/petrinets_constraints
  47. 1 1
      interface/HUTN/test/modelling_language/expected/simpleclassdiagrams
  48. 1 0
      scripts/run_MvC_server.py

+ 62 - 2
bootstrap/conformance_scd.alc

@@ -45,6 +45,7 @@ Element function precompute_cardinalities(model : Element):
 	Element cardinalities
 	Element keys
 	Element metamodel
+	Boolean optional
 
 	metamodel = model["metamodel"]
 	keys = allInstances(metamodel, "Association")
@@ -70,6 +71,24 @@ Element function precompute_cardinalities(model : Element):
 		if (list_len(tmp_dict) > 0):
 			dict_add(cardinalities, key, tmp_dict)
 
+	keys = allInstances(metamodel, "AttributeLink")
+	while (0 < list_len(keys)):
+		key = set_pop(keys)
+		tmp_dict = create_node()
+
+		// Attributes always have 1 max
+		dict_add(tmp_dict, "tuc", 1)
+
+		// Depending on whether it is optional or not, the cardinality is changed
+		optional = read_attribute(metamodel, key, "optional")
+		if (optional):
+			dict_add(tmp_dict, "tlc", 0)
+		else:
+			dict_add(tmp_dict, "tlc", 1)
+
+		if (list_len(tmp_dict) > 0):
+			dict_add(cardinalities, key, tmp_dict)
+
 	return cardinalities!
 
 String function conformance_scd(model : Element):
@@ -128,10 +147,14 @@ String function conformance_scd(model : Element):
 				dst_metamodel = reverseKeyLookup(metamodel["model"], read_edge_dst(metamodel["model"][typing[model_name]]))
 
 				if (bool_not(is_nominal_instance(model, src_model, src_metamodel))):
+					log("got: " + src_model)
+					log("expected: " + src_metamodel)
 					return "Source of model edge not typed by source of type: " + model_info(model, model_name)!
 
 				if (bool_not(is_nominal_instance(model, dst_model, dst_metamodel))):
-					return "Destination of model edge not typed by source of type: " + model_info(model, model_name)!
+					log("got: " + dst_model)
+					log("expected: " + dst_metamodel)
+					return "Destination of model edge not typed by destination of type: " + model_info(model, model_name)!
 
 			// Check cardinality for all of our edges
 			//
@@ -189,7 +212,11 @@ String function conformance_scd(model : Element):
 			constraint_function = read_attribute(metamodel, typing[model_name], "constraint")
 			if (element_neq(constraint_function, read_root())):
 				String result
-				result = constraint_function(model, model_name)
+				Element func
+
+				func = get_func_AL_model(constraint_function)
+				result = func(model, model_name)
+
 				if (result != "OK"):
 					return result!
 
@@ -216,6 +243,26 @@ String function conformance_scd(model : Element):
 			if (attr_value < list_len(allInstances(model, metamodel_element))):
 				return "Upper cardinality violated for class: " + metamodel_element!
 
+	// Check all ComplexAttributes recursively
+	Element all_complex_types
+	Element complex_instances
+	String complex_instance
+	String complex_type
+	String result
+	all_complex_types = allInstances(model["metamodel"]["metamodel"], "ComplexAttribute")
+	while (read_nr_out(all_complex_types) > 0):
+		complex_type = set_pop(all_complex_types)
+		complex_instances = allInstances(model, complex_type)
+
+		while (read_nr_out(complex_instances) > 0):
+			complex_instance = set_pop(complex_instances)
+
+			complex_type = read_attribute(model["metamodel"], read_type(model, complex_instance), "type")
+			result = check_location_conformance(model["model"][complex_instance], complex_type)
+
+			if (result != "OK"):
+				return ((("Complex attribute doesn't match for: " + complex_instance) + "\n Message: ") + result)!
+
 	// Structure seems fine, now do static semantics
 	if (dict_in(metamodel, "constraints")):
 		Element constraint_function
@@ -224,6 +271,19 @@ String function conformance_scd(model : Element):
 	else:
 		return "OK"!
 
+String function check_location_conformance(instance_location : String, type_location : String):
+	// Check whether the instance is typed by the type
+	Element instance
+	Element type
+
+	instance = import_node(instance_location)
+	type = import_node(type_location)
+
+	if (element_neq(instance["metamodel"], type)):
+		return "Instance not statically typed by specified metamodel"!
+	
+	return conformance_scd(instance)!
+
 Element function set_model_constraints(model : Element, func : Element):
 	if (dict_in(model, "constraints")):
 		dict_delete(model, "constraints")

+ 143 - 250
bootstrap/metamodels.alc

@@ -4,225 +4,139 @@ include "library.alh"
 include "conformance_scd.alh"
 include "modelling.alh"
 
-Element function constraint_natural(model : Element, name : String):
-	if (is_physical_int(model["model"][name])):
-		if (integer_gte(model["model"][name], 0)):
+String function constraint_Natural(model : Element, name : String):
+	Element self
+	self = model["model"][name]
+	if (is_physical_int(self)):
+		if (integer_gte(self, 0)):
 			return "OK"!
 		else:
 			return "Natural number not larger than or equal to zero"!
 	else:
-		return "Natural has non-integer instance"!
+		return "Natural number not larger than or equal to zero"!
 
-Element function constraint_string(model : Element, name : String):
-	if (is_physical_string(model["model"][name])):
+Element function constraint_String(model : Element, name : String):
+	Element self
+	log("Invoked!")
+	self = model["model"][name]
+	if (is_physical_string(self)):
 		return "OK"!
 	else:
 		return "String has non-string instance"!
 
-Element function constraint_if(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "if"):
-			return "OK"!
-		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
-	else:
-		return "Expected physical action value"!
-
-Element function constraint_while(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "while"):
-			return "OK"!
-		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
-	else:
-		return "Expected physical action value"!
-
-Element function constraint_break(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "break"):
-			return "OK"!
-		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
-	else:
-		return "Expected physical action value"!
-
-Element function constraint_continue(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "continue"):
-			return "OK"!
-		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
-	else:
-		return "Expected physical action value"!
-
-Element function constraint_assign(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "assign"):
-			return "OK"!
-		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
-	else:
-		return "Expected physical action value"!
-
-Element function constraint_return(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "return"):
-			return "OK"!
-		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
-	else:
-		return "Expected physical action value"!
-
-Element function constraint_output(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "output"):
-			return "OK"!
-		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
-	else:
-		return "Expected physical action value"!
-
-Element function constraint_input(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "input"):
-			return "OK"!
-		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
-	else:
-		return "Expected physical action value"!
-
-Element function constraint_declare(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "declare"):
-			return "OK"!
-		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
-	else:
-		return "Expected physical action value"!
-
-Element function constraint_global(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "global"):
-			return "OK"!
-		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
-	else:
-		return "Expected physical action value"!
-
-Element function constraint_access(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "access"):
-			return "OK"!
-		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
-	else:
-		return "Expected physical action value"!
-
-Element function constraint_constant(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "constant"):
-			return "OK"!
-		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+Element function constraint_Boolean(model : Element, name : String):
+	Element self
+	self = model["model"][name]
+	if (is_physical_boolean(self)):
+		return "OK"!
 	else:
-		return "Expected physical action value"!
+		return "Boolean has non-boolean instance"!
 
-Element function constraint_resolve(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "resolve"):
+Element function constraint_Location(model : Element, name : String):
+	Element self
+	self = model["model"][name]
+	if (is_physical_string(self)):
+		if (element_neq(import_node(self), read_root())):
 			return "OK"!
 		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+			return "Location references non-existing element!"!
 	else:
-		return "Expected physical action value"!
+		return "Location has non-string instance"!
 
-Element function constraint_call(model : Element, name : String):
-	if (is_physical_action(model["model"][name])):
-		if (cast_a2s(model["model"][name]) == "call"):
+Element function constraint_ActionLanguage(model : Element, name : String):
+	Element self
+	self = model["model"][name]
+	if (is_physical_string(self)):
+		if (element_neq(import_node(self), read_root())):
 			return "OK"!
 		else:
-			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+			return "ActionLanguage references non-existing element!"!
 	else:
-		return "Expected physical action value"!
+		return "ActionLanguage has non-string value!"!
 
 Element function initialize_SCD(location : String):
 	if (element_neq(import_node(location), read_root())):
 		return import_node(location)!
 
 	Element scd
+	String al_location
+	al_location = "models/ActionLanguage"
+
 	scd = instantiate_bottom()
 
-	// Initial model, typed using LTM_bottom
+	model_add_node(scd, "Element")
 	model_add_node(scd, "Class")
-	model_add_node(scd, "Any")
+	model_add_node(scd, "Attribute")
+	model_add_node(scd, "SimpleAttribute")
 	model_add_node(scd, "String")
-	model_add_value(scd, "name", "name")
-	model_add_edge(scd, "Association", "Class", "Any")
-	model_add_edge(scd, "Inheritance", "Class", "Class")
-	model_add_edge(scd, "Association_attribute", "Association", "String")
-	model_add_edge(scd, "Association_name", "Association_attribute", "name")
-	model_add_edge(scd, "assoc_inh_class", "Association", "Class")
-	model_add_edge(scd, "class_inh_any", "Class", "Any")
-	model_add_edge(scd, "string_inh_any", "String", "Any")
-
-	// Retype to a "real" LTM, which happens to be itself
+	model_add_value(scd, "name_value", "name")
+	model_add_edge(scd, "Association", "Class", "Class")
+	model_add_edge(scd, "Inheritance", "Element", "Element")
+	model_add_edge(scd, "AttributeLink", "Element", "Attribute")
+	model_add_edge(scd, "attr_name", "AttributeLink", "String")
+	model_add_edge(scd, "attr_name_name", "attr_name", "name_value")
+	model_add_edge(scd, "class_inh_element", "Class", "Element")
+	model_add_edge(scd, "attribute_inh_element", "Attribute", "Element")
+	model_add_edge(scd, "simple_inh_attribute", "SimpleAttribute", "Attribute")
+	model_add_edge(scd, "association_inh_element", "Association", "Element")
+	model_add_edge(scd, "attributelink_inh_element", "AttributeLink", "Element")
+
+	// Retype to self
 	retype_model(scd, scd)
+	retype(scd, "Element", "Class")
 	retype(scd, "Class", "Class")
-	retype(scd, "Any", "Class")
-	retype(scd, "String", "Class")
-	retype(scd, "name", "String")
+	retype(scd, "Attribute", "Class")
+	retype(scd, "SimpleAttribute", "Class")
+	retype(scd, "String", "SimpleAttribute")
+	retype(scd, "name_value", "String")
 	retype(scd, "Association", "Association")
 	retype(scd, "Inheritance", "Association")
-	retype(scd, "Association_attribute", "Association")
-	retype(scd, "Association_name", "Association_attribute")
-	retype(scd, "assoc_inh_class", "Inheritance")
-	retype(scd, "class_inh_any", "Inheritance")
-	retype(scd, "string_inh_any", "Inheritance")
+	retype(scd, "AttributeLink", "Association")
+	retype(scd, "attr_name", "AttributeLink")
+	retype(scd, "attr_name_name", "attr_name")
+	retype(scd, "class_inh_element", "Inheritance")
+	retype(scd, "attribute_inh_element", "Inheritance")
+	retype(scd, "simple_inh_attribute", "Inheritance")
+	retype(scd, "association_inh_element", "Inheritance")
+	retype(scd, "attributelink_inh_element", "Inheritance")
 
 	// Add some attributes, now that it is an ordinary model
-	instantiate_node(scd, "Class", "Natural")
-	instantiate_link(scd, "Association", "lc", "Class", "Natural")
-	instantiate_attribute(scd, "lc", "name", "lower_cardinality")
-	instantiate_link(scd, "Association", "uc", "Class", "Natural")
-	instantiate_attribute(scd, "uc", "name", "upper_cardinality")
-	instantiate_link(scd, "Association", "slc", "Association", "Natural")
-	instantiate_attribute(scd, "slc", "name", "source_lower_cardinality")
-	instantiate_link(scd, "Association", "suc", "Association", "Natural")
-	instantiate_attribute(scd, "suc", "name", "source_upper_cardinality")
-	instantiate_link(scd, "Association", "tlc", "Association", "Natural")
-	instantiate_attribute(scd, "tlc", "name", "target_lower_cardinality")
-	instantiate_link(scd, "Association", "tuc", "Association", "Natural")
-	instantiate_attribute(scd, "tuc", "name", "target_upper_cardinality")
-
-	// Add in the Action Language metamodel
-	add_AL_to_MM(scd)
-
-	// Now still allow for constraints on classes
-	instantiate_link(scd, "Association", "constraint", "Class", "funcdef")
-	instantiate_attribute(scd, "constraint", "name", "constraint")
-
-	// Add constraints to all primitive classes
-	//add_constraint(scd, "if", constraint_if)
-	//add_constraint(scd, "while", constraint_while)
-	//add_constraint(scd, "break", constraint_break)
-	//add_constraint(scd, "continue", constraint_continue)
-	//add_constraint(scd, "assign", constraint_assign)
-	//add_constraint(scd, "return", constraint_return)
-	//add_constraint(scd, "output", constraint_output)
-	//add_constraint(scd, "input", constraint_input)
-	//add_constraint(scd, "declare", constraint_declare)
-	//add_constraint(scd, "global", constraint_global)
-	//add_constraint(scd, "access", constraint_access)
-	//add_constraint(scd, "constant", constraint_constant)
-	//add_constraint(scd, "resolve", constraint_resolve)
-	//add_constraint(scd, "call", constraint_call)
-
-	// And add some, to enforce correct physical types
-	add_constraint(scd, "Natural", constraint_natural)
-	add_constraint(scd, "String", constraint_string)
-
-	// Finally done, so export!
+	instantiate_node(scd, "SimpleAttribute", "Location")
+	instantiate_node(scd, "SimpleAttribute", "Natural")
+	instantiate_node(scd, "SimpleAttribute", "Boolean")
+	instantiate_link(scd, "AttributeLink", "attr_optional", "AttributeLink", "Boolean")
+	instantiate_attribute(scd, "attr_optional", "name", "optional")
+	instantiate_attribute(scd, "attr_optional", "optional", False)
+	instantiate_attribute(scd, "attr_name", "optional", False)
+
+	instantiate_node(scd, "Class", "ComplexAttribute")
+	instantiate_link(scd, "Inheritance", "", "ComplexAttribute", "Attribute")
+
+	model_define_attribute(scd, "Class", "lower_cardinality", True, "Natural")
+	model_define_attribute(scd, "Class", "upper_cardinality", True, "Natural")
+	model_define_attribute(scd, "Association", "source_lower_cardinality", True, "Natural")
+	model_define_attribute(scd, "Association", "target_lower_cardinality", True, "Natural")
+	model_define_attribute(scd, "Association", "source_upper_cardinality", True, "Natural")
+	model_define_attribute(scd, "Association", "target_upper_cardinality", True, "Natural")
+	model_define_attribute(scd, "ComplexAttribute", "type", False, "Location")
+
+	// Export already, to allow AL to pick it up
 	export_node(location, scd)
+	// Add in the Action Language metamodel
+	initialize_AL(location, al_location)
+
+	// Define additional attributes that define functions
+	instantiate_node(scd, "ComplexAttribute", "ActionLanguage")
+	instantiate_attribute(scd, "ActionLanguage", "type", al_location)
+	model_define_attribute(scd, "Element", "constraint", True, "ActionLanguage")
+
+	// Define some constraints
+	instantiate_attribute_code(scd, "Natural", "constraint", constraint_Natural)
+	instantiate_attribute_code(scd, "String", "constraint", constraint_String)
+	instantiate_attribute_code(scd, "Boolean", "constraint", constraint_Boolean)
+	instantiate_attribute_code(scd, "Location", "constraint", constraint_Location)
+	instantiate_attribute_code(scd, "ActionLanguage", "constraint", constraint_ActionLanguage)
+
 	return scd!
 
 Element function initialize_PN(location_SCD : String, location_PN : String):
@@ -234,24 +148,15 @@ Element function initialize_PN(location_SCD : String, location_PN : String):
 	pn = instantiate_model(scd)
 	instantiate_node(pn, "Class", "Place")
 	instantiate_node(pn, "Class", "Transition")
-	instantiate_node(pn, "Class", "Natural")
+	instantiate_node(pn, "SimpleAttribute", "Natural")
 	instantiate_link(pn, "Association", "P2T", "Place", "Transition")
 	instantiate_link(pn, "Association", "T2P", "Transition", "Place")
-	instantiate_link(pn, "Association", "Place_tokens", "Place", "Natural")
-	instantiate_attribute(pn, "Place_tokens", "name", "tokens")
-	instantiate_attribute(pn, "Place_tokens", "target_lower_cardinality", 1)
-	instantiate_attribute(pn, "Place_tokens", "target_upper_cardinality", 1)
-	instantiate_link(pn, "Association", "P2T_weight", "P2T", "Natural")
-	instantiate_attribute(pn, "P2T_weight", "name", "weight")
-	instantiate_attribute(pn, "P2T_weight", "target_lower_cardinality", 1)
-	instantiate_attribute(pn, "P2T_weight", "target_upper_cardinality", 1)
-	instantiate_link(pn, "Association", "T2P_weight", "T2P", "Natural")
-	instantiate_attribute(pn, "T2P_weight", "name", "weight")
-	instantiate_attribute(pn, "T2P_weight", "target_lower_cardinality", 1)
-	instantiate_attribute(pn, "T2P_weight", "target_upper_cardinality", 1)
+	model_define_attribute(pn, "Place", "tokens", False, "Natural")
+	model_define_attribute(pn, "P2T", "weight", False, "Natural")
+	model_define_attribute(pn, "T2P", "weight", False, "Natural")
 
 	// Add constraint on the Natural
-	add_constraint(pn, "Natural", constraint_natural)
+	instantiate_attribute_code(pn, "Natural", "constraint", constraint_Natural)
 
 	export_node(location_PN, pn)
 
@@ -293,7 +198,17 @@ Element function create_metamodels():
 
 	return dict_read(dict_read(read_root(), "__hierarchy"), "models")!
 
-Void function add_AL_to_MM(model : Element):
+Void function initialize_AL(scd_location : String, export_location : String):
+	Element model
+	Element scd_model
+
+	if (element_neq(import_node(export_location), read_root())):
+		return!
+
+	scd_model = import_node(scd_location)
+	model = instantiate_model(scd_model)
+
+	instantiate_node(model, "Class", "Element")
 	instantiate_node(model, "Class", "Action")
 	instantiate_node(model, "Class", "Statement")
 	instantiate_node(model, "Class", "Expression")
@@ -313,10 +228,17 @@ Void function add_AL_to_MM(model : Element):
 	instantiate_node(model, "Class", "input")
 	instantiate_node(model, "Class", "resolve")
 	instantiate_node(model, "Class", "call")
-	instantiate_link(model, "Association", "dict_link", "Action", "Any")
-	instantiate_link(model, "Association", "to_str", "dict_link", "String")
-	instantiate_attribute(model, "to_str", "name", "name")
-	instantiate_link(model, "Inheritance", "", "Action", "Any")
+	instantiate_node(model, "Class", "String")
+	instantiate_node(model, "SimpleAttribute", "StringAttr")
+	instantiate_node(model, "Class", "Initial")
+
+	instantiate_attribute(model, "Initial", "lower_cardinality", 1)
+	instantiate_attribute(model, "Initial", "upper_cardinality", 1)
+	instantiate_link(model, "Association", "initial_funcdef", "Initial", "Action")
+	instantiate_attribute(model, "initial_funcdef", "target_lower_cardinality", 1)
+	instantiate_attribute(model, "initial_funcdef", "target_upper_cardinality", 1)
+
+	instantiate_link(model, "Inheritance", "", "Action", "Element")
 	instantiate_link(model, "Inheritance", "", "funcdef", "Action")
 	instantiate_link(model, "Inheritance", "", "param", "Action")
 	instantiate_link(model, "Inheritance", "", "Statement", "Action")
@@ -335,20 +257,26 @@ Void function add_AL_to_MM(model : Element):
 	instantiate_link(model, "Inheritance", "", "access", "Expression")
 	instantiate_link(model, "Inheritance", "", "constant", "Expression")
 	instantiate_link(model, "Inheritance", "", "input", "Expression")
-	instantiate_link(model, "Association", "statement_next", "Statement", "Statement")
+	instantiate_link(model, "Inheritance", "", "String", "Element")
+
+	instantiate_link(model, "Association", "dict_link", "Action", "Element")
+	model_define_attribute(model, "dict_link", "name", False, "StringAttr")
+	instantiate_attribute(model, "dict_link", "target_upper_cardinality", 1)
+
+	instantiate_link(model, "Association", "Statement_next", "Statement", "Statement")
 	instantiate_link(model, "Association", "if_cond", "if", "Expression")
 	instantiate_link(model, "Association", "if_then", "if", "Statement")
 	instantiate_link(model, "Association", "if_else", "if", "Statement")
 	instantiate_link(model, "Association", "while_cond", "while", "Expression")
 	instantiate_link(model, "Association", "while_body", "while", "Statement")
-	instantiate_link(model, "Association", "assign_var", "assign", "Any")
+	instantiate_link(model, "Association", "assign_var", "assign", "resolve")
 	instantiate_link(model, "Association", "assign_value", "assign", "Expression")
 	instantiate_link(model, "Association", "break_while", "break", "while")
 	instantiate_link(model, "Association", "continue_while", "continue", "while")
 	instantiate_link(model, "Association", "return_value", "return", "Expression")
-	instantiate_link(model, "Association", "resolve_var", "resolve", "Any")
-	instantiate_link(model, "Association", "access_var", "access", "Any")
-	instantiate_link(model, "Association", "constant_node", "constant", "Any")
+	instantiate_link(model, "Association", "resolve_var", "resolve", "Element")
+	instantiate_link(model, "Association", "access_var", "access", "resolve")
+	instantiate_link(model, "Association", "constant_node", "constant", "Element")
 	instantiate_link(model, "Association", "output_node", "output", "Expression")
 	instantiate_link(model, "Association", "global_var", "global", "String")
 	instantiate_link(model, "Association", "param_name", "param", "String")
@@ -358,7 +286,7 @@ Void function add_AL_to_MM(model : Element):
 	instantiate_link(model, "Association", "call_func", "call", "Expression")
 	instantiate_link(model, "Association", "call_params", "call", "param")
 	instantiate_link(model, "Association", "call_last_param", "call", "param")
-	instantiate_link(model, "Inheritance", "", "statement_next", "dict_link")
+	instantiate_link(model, "Inheritance", "", "Statement_next", "dict_link")
 	instantiate_link(model, "Inheritance", "", "if_cond", "dict_link")
 	instantiate_link(model, "Inheritance", "", "if_then", "dict_link")
 	instantiate_link(model, "Inheritance", "", "if_else", "dict_link")
@@ -382,46 +310,11 @@ Void function add_AL_to_MM(model : Element):
 	instantiate_link(model, "Inheritance", "", "call_params", "dict_link")
 	instantiate_link(model, "Inheritance", "", "call_last_param", "dict_link")
 
-	// Add cardinalities on how many connections are allowed: one of each
-	instantiate_attribute(model, "statement_next", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "if_cond", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "if_cond", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "if_then", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "if_then", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "if_else", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "while_cond", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "while_cond", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "while_body", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "while_body", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "assign_var", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "assign_var", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "assign_value", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "assign_value", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "break_while", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "break_while", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "continue_while", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "continue_while", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "return_value", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "resolve_var", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "resolve_var", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "access_var", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "access_var", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "constant_node", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "constant_node", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "output_node", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "output_node", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "global_var", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "global_var", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "param_name", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "param_name", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "param_value", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "param_value", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "param_next_param", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "funcdef_body", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "funcdef_body", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "call_func", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "call_func", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "call_params", "target_upper_cardinality", 1)
-	instantiate_attribute(model, "call_last_param", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "if_else", "target_lower_cardinality", 1)
+	instantiate_attribute(model, "return_value", "target_lower_cardinality", 1)
+	instantiate_attribute(model, "param_next_param", "target_lower_cardinality", 1)
+	instantiate_attribute(model, "call_params", "target_lower_cardinality", 1)
+	instantiate_attribute(model, "call_last_param", "target_lower_cardinality", 1)
 
+	export_node(export_location, model)
 	return !

+ 104 - 45
bootstrap/modelling.alc

@@ -108,6 +108,9 @@ String function instantiate_node(model : Element, type_name : String, instance_n
 		log("    for " + instance_name)
 		return ""!
 
+	if (dict_in(model["model"], instance_name)):
+		return ""!
+
 	actual_name = model_add_node(model, instance_name)
 	retype(model, actual_name, type_name)
 
@@ -123,6 +126,9 @@ String function instantiate_value(model : Element, type_name : String, instance_
 		log("     for " + instance_name)
 		return ""!
 
+	if (dict_in(model["model"], instance_name)):
+		return ""!
+
 	actual_name = model_add_value(model, instance_name, value)
 	retype(model, actual_name, type_name)
 
@@ -207,11 +213,15 @@ Void function instantiate_attribute(model : Element, element : String, attribute
 	String attr_type
 	String attr_name
 
+	if (element_neq(read_attribute(model, element, attribute_name), read_root())):
+		unset_attribute(model, element, attribute_name)
+
 	attr_type = find_attribute_type(model, element, attribute_name)
 
 	if (attr_type == ""):
 		log("Could not find attribute " + cast_v2s(attribute_name))
 		log("For element " + element)
+		log("Type: " + read_type(model, element))
 		return!
 
 	if (has_value(value)):
@@ -239,10 +249,23 @@ Void function instantiate_attribute_ref(model : Element, element : String, attri
 
 	return!
 
+Void function add_code_model(model : Element, export_name : String, code : Element):
+	Element code_model
+	code_model = instantiate_model(model)
+	add_AL(code_model, code)
+	export_node(export_name, code_model)
+
+	return !
+
 Void function instantiate_attribute_code(model : Element, element : String, attribute_name : String, code : Element):
-	String ref
-	ref = add_AL(model, code)
-	instantiate_existing_attribute(model, element, attribute_name, ref)
+	// First create a new model for the AL part
+	String location
+	location = "code/" + cast_id2s(code)
+
+	add_code_model(import_node("models/ActionLanguage"), location, code)
+
+	// Now link it with a complex attribute
+	instantiate_attribute(model, element, attribute_name, location)
 
 	return!
 
@@ -268,6 +291,9 @@ String function instantiate_link(model : Element, type : String, name : String,
 	// Create a typed link between two nodes
 	String actual_name
 
+	if (dict_in(model["model"], name)):
+		return ""!
+
 	if (type == ""):
 		// Have to find the type ourselves, as it isn't defined
 		Element out
@@ -305,12 +331,19 @@ Void function model_delete_element(model : Element, name : String):
 
 	return!
 
-String function model_define_attribute(model : Element, elem : String, name : String, type : String):
+String function model_define_attribute(model : Element, elem : String, name : String, optional : Boolean, type : String):
 	// Create the necessary links to make it an attribute
 	String edge_name
 
-	edge_name = instantiate_link(model, "Association", "", elem, type)
+	edge_name = (elem + "_") + name
+	while (dict_in(model["model"], edge_name)):
+		// Already exists, so make random name
+		edge_name = edge_name + cast_id2s(model["model"][elem])
+		log("Name clash detected for attribute: try new name: " + edge_name)
+
+	edge_name = instantiate_link(model, "AttributeLink", edge_name, elem, type)
 	instantiate_attribute(model, edge_name, "name", name)
+	instantiate_attribute(model, edge_name, "optional", optional)
 
 	return edge_name!
 
@@ -323,20 +356,25 @@ Element function read_attribute(model : Element, element : String, attribute : S
 	Element typing
 	Element name
 
-	elem = model["model"][element]
-	typing = model["type_mapping"]
-	count = read_nr_out(elem)
+	if (dict_in(model["model"], element)):
+		elem = model["model"][element]
+		typing = model["type_mapping"]
+		count = read_nr_out(elem)
+
+		i = 0
+		while (i < count):
+			edge = read_out(elem, i)
+			name = reverseKeyLookup(model["model"], edge)
+			if (dict_in(typing, name)):
+				edge_type_name = typing[name]
+				if (edge_type_name == reverseKeyLookup(model["metamodel"]["model"], dict_read_edge(read_edge_src(model["metamodel"]["model"][edge_type_name]), attribute))):
+					return read_edge_dst(edge)!
+			i = i + 1
 
-	i = 0
-	while (i < count):
-		edge = read_out(elem, i)
-		name = reverseKeyLookup(model["model"], edge)
-		if (dict_in(typing, name)):
-			edge_type_name = typing[name]
-			if (edge_type_name == reverseKeyLookup(model["metamodel"]["model"], dict_read_edge(read_edge_src(model["metamodel"]["model"][edge_type_name]), attribute))):
-				return read_edge_dst(edge)!
-		i = i + 1
+	else:
+		log("Element does not exist!")
 
+	// Not found: either element doesn't exist, or we couldn't find it
 	return read_root()!
 
 Void function unset_attribute(model : Element, element : String, attribute : String):
@@ -376,22 +414,18 @@ Void function add_AL_links(model : Element, list : Element, element : Element, t
 	link_name = "__" + cast_id2s(link)
 
 	dict_add(model["model"], link_name, link)
-	dict_add(model["type_mapping"], link_name, "to_str")
-
+	dict_add(model["type_mapping"], link_name, "dict_link_name")
+	
 	// The name node
 	link = read_edge_dst(link)
 	link_name = "__" + cast_id2s(link)
 
 	if (bool_not(set_in_node(model["model"], link))):
 		dict_add(model["model"], link_name, link)
-		dict_add(model["type_mapping"], link_name, "String")
+		dict_add(model["type_mapping"], link_name, "StringAttr")
 
 	// Now add the destination to the worker list
-	Element node
-	node = create_node()
-	list_append(node, element[linkname])
-	list_append(node, expected_type)
-	set_add(list, node)
+	set_add(list, create_tuple(element[linkname], expected_type))
 
 	return!
 
@@ -420,7 +454,7 @@ String function add_AL(model : Element, element : Element):
 				if (is_physical_action(elem)):
 					type = cast_a2s(elem)
 				else:
-					type = "Any"
+					type = "Element"
 
 			// Add the node itself
 			elem_name = "__" + cast_id2s(elem)
@@ -438,7 +472,7 @@ String function add_AL(model : Element, element : Element):
 				add_AL_links(model, todo, elem, type, "body", "")
 				add_AL_links(model, todo, elem, type, "next", "")
 			elif (type == "assign"):
-				add_AL_links(model, todo, elem, type, "var", "")
+				add_AL_links(model, todo, elem, type, "var", "resolve")
 				add_AL_links(model, todo, elem, type, "value", "")
 				add_AL_links(model, todo, elem, type, "next", "")
 			elif (type == "break"):
@@ -450,7 +484,7 @@ String function add_AL(model : Element, element : Element):
 			elif (type == "resolve"):
 				add_AL_links(model, todo, elem, type, "var", "")
 			elif (type == "access"):
-				add_AL_links(model, todo, elem, type, "var", "")
+				add_AL_links(model, todo, elem, type, "var", "resolve")
 			elif (type == "constant"):
 				add_AL_links(model, todo, elem, type, "node", "")
 			elif (type == "output"):
@@ -465,6 +499,8 @@ String function add_AL(model : Element, element : Element):
 				add_AL_links(model, todo, elem, type, "next_param", "param")
 			elif (type == "funcdef"):
 				add_AL_links(model, todo, elem, type, "body", "")
+				// TODO this should be added, but is not the same as "param"
+				//add_AL_links(model, todo, elem, type, "params", "")
 				add_AL_links(model, todo, elem, type, "next", "")
 			elif (type == "call"):
 				add_AL_links(model, todo, elem, type, "func", "")
@@ -472,19 +508,12 @@ String function add_AL(model : Element, element : Element):
 				add_AL_links(model, todo, elem, type, "last_param", "param")
 				add_AL_links(model, todo, elem, type, "next", "")
 
-	return reverseKeyLookup(model["model"], element)!
-
-Void function add_constraint(model : Element, element : String, constraint : Action):
-	// Add local constraints to an element
-	Element attr_type
-	String link_name
-	String constraint_name
+	// Mark the node as first
+	String initial
+	initial = instantiate_node(model, "Initial", "")
+	instantiate_link(model, "initial_funcdef", "", initial, reverseKeyLookup(model["model"], element))
 
-	constraint_name = add_AL(model, constraint)
-	attr_type = find_attribute_type(model, element, "constraint")
-	instantiate_link(model, attr_type, "", element, constraint_name)
-
-	return!
+	return reverseKeyLookup(model["model"], element)!
 
 Void function construct_model():
 	String command
@@ -523,8 +552,8 @@ Void function construct_model():
 			instantiate_attribute_code(global_models[input()], input(), input(), construct_function())
 		elif (command == "instantiate_link"):
 			instantiate_link(global_models[input()], input(), input(), input(), input())
-		elif (command == "add_constraint"):
-			add_constraint(global_models[input()], input(), construct_function())
+		elif (command == "model_define_attribute"):
+			model_define_attribute(global_models[input()], input(), input(), input(), input())
 		elif (command == "initialize_SCD"):
 			initialize_SCD(input())
 		elif (command == "initialize_bottom"):
@@ -543,6 +572,8 @@ Void function construct_model():
 				log("Error: import not found for " + command)
 			else:
 				dict_add(global_models, input(), m)
+		elif (command == "add_code_model"):
+			add_code_model(global_models[input()], input(), construct_function())
 		else:
 			log("Modelling error: did not understand command " + command)
 
@@ -568,6 +599,9 @@ Element function construct_model_raw(metamodel : Element):
 		elif (command == "instantiate_node"):
 			input()
 			instantiate_node(model, input(), input())
+		elif (command == "model_define_attribute"):
+			input()
+			model_define_attribute(model, input(), input(), input(), input())
 		elif (command == "instantiate_attribute"):
 			input()
 			instantiate_attribute(model, input(), input(), input())
@@ -580,9 +614,6 @@ Element function construct_model_raw(metamodel : Element):
 		elif (command == "instantiate_link"):
 			input()
 			instantiate_link(model, input(), input(), input(), input())
-		elif (command == "add_constraint"):
-			input()
-			add_constraint(model, input(), construct_function())
 		elif (command == "import_node"):
 			input()
 			input()
@@ -592,5 +623,33 @@ Element function construct_model_raw(metamodel : Element):
 		elif (command == "instantiate_model"):
 			input()
 			input()
+		elif (command == "add_code_model"):
+			input()
+			add_code_model(model, input(), construct_function())
 		else:
 			log("Modelling error: did not understand command " + command)
+
+Element function get_func_AL_model(model_location : String):
+	Element result
+	Element al_model
+	Element initial_function
+
+	// Fetch the model to execute
+	al_model = import_node(model_location)
+
+	// Find the initial function
+	initial_function = allInstances(al_model, "Initial")
+
+	if (read_nr_out(initial_function) == 0):
+		log("Could not find function to execute in this model!")
+		return create_node()!
+	elif (read_nr_out(initial_function) > 1):
+		log("Too many functions to execute in this model!")
+		return create_node()!
+	else:
+		initial_function = al_model["model"][set_pop(allAssociationDestinations(al_model, set_pop(initial_function), "initial_funcdef"))]
+		log("Found initial_function: " + cast_e2s(initial_function))
+		log("Keys: " + set_to_string(dict_keys(initial_function)))
+		log("Resolved " + model_location)
+
+	return initial_function!

+ 14 - 9
bootstrap/object_operations.alc

@@ -14,6 +14,8 @@ Element function allInstances(model : Element, type_name : String):
 	type = model["metamodel"]["model"][type_name]
 	result = create_node()
 
+	// TODO more efficient to work backwards: find all instances of an element through the type mapping directly
+	//      must then take into account all inheritance links ourselves...
 	while (0 < list_len(keys)):
 		key = set_pop(keys)
 		if (is_nominal_instance(model, key, type_name)):
@@ -64,19 +66,22 @@ Element function selectPossibleOutgoing(model : Element, source : String, limit_
 
 Element function allOutgoingAssociationInstances(model : Element, source_name : String, assoc_name : String):
 	// Read out all outgoing edges of the model and select those that are typed by the specified association
-	Element assocs
-	String assoc
 	Element result
 	Element source
+	String option
+	Integer all_out
+	Integer i
 
-	assocs = allInstances(model, assoc_name)
+	result = create_node()
 	source = model["model"][source_name]
+	all_out = read_nr_out(source)
+	i = 0
+	while (i < all_out):
+		option = reverseKeyLookup(model["model"], read_out(source, i))
+		if (is_nominal_instance(model, option, assoc_name)):
+			set_add(result, option)
+		i = i + 1
 
-	result = create_node()
-	while (0 < list_len(assocs)):
-		assoc = set_pop(assocs)
-		if (element_eq(source, read_edge_src(model["model"][assoc]))):
-			set_add(result, assoc)
 	return result!
 
 Element function allIncomingAssociationInstances(model : Element, target_name : String, assoc_name : String):
@@ -261,5 +266,5 @@ String function read_type(model : Element, name : String):
 			log("Type mapping: " + dict_to_string(model["type_mapping"]))
 			return ""!
 	else:
-		log("Couldn't find " + name)
+		log("Couldn't find type of " + name)
 		return ""!

+ 102 - 100
bootstrap/ramify.alc

@@ -3,6 +3,7 @@ include "object_operations.alh"
 include "modelling.alh"
 include "metamodels.alh"
 include "model_management.alh"
+include "conformance_scd.alh"
 
 Element function ramify(model : Element):
 	// Create new model structure
@@ -24,27 +25,32 @@ Element function ramify(model : Element):
 	mm = new_model["metamodel"]["model"]
 
 	// Add in some primitives
-	instantiate_node(new_model, "Class", "Natural")
-	instantiate_node(new_model, "Class", "String")
-	instantiate_node(new_model, "Class", "Any")
+	instantiate_node(new_model, "SimpleAttribute", "Natural")
+	instantiate_attribute(new_model, "Natural", "constraint", constraint_Natural)
 
-	// Add in the complete AL metamodel
-	add_AL_to_MM(new_model)
+	instantiate_node(new_model, "SimpleAttribute", "String")
+	instantiate_attribute(new_model, "String", "constraint", constraint_String)
+
+	instantiate_node(new_model, "SimpleAttribute", "Boolean")
+	instantiate_attribute(new_model, "Boolean", "constraint", constraint_Boolean)
+
+	instantiate_node(new_model, "SimpleAttribute", "Location")
+	instantiate_attribute(new_model, "Location", "constraint", constraint_Location)
+
+	instantiate_node(new_model, "ComplexAttribute", "ActionLanguage")
+	instantiate_attribute(new_model, "ActionLanguage", "constraint", constraint_ActionLanguage)
+	model_define_attribute(new_model, "ActionLanguage", "type", False, "Location")
 
 	// Add some default elements
 	//	Class LHS_Root {
-	//		constraint : funcdef {
-	//			target_upper_cardinality = 1
-	//		}
+	//		constraint? : ActionLanguage
 	//		upper_cardinality = 1
 	//		lower_cardinality = 1
 	//	}
 	instantiate_node(new_model, "Class", "LHS_Root")
 	instantiate_attribute(new_model, "LHS_Root", "lower_cardinality", 1)
 	instantiate_attribute(new_model, "LHS_Root", "upper_cardinality", 1)
-	instantiate_link(new_model, "Association", "LHS_constraint", "LHS_Root", "funcdef")
-	instantiate_attribute(new_model, "LHS_constraint", "name", "constraint")
-	instantiate_attribute(new_model, "LHS_constraint", "target_upper_cardinality", 1)
+	model_define_attribute(new_model, "LHS_Root", "constraint", True, "ActionLanguage")
 
 	//  Class LHS : LHS_Root {}
 	instantiate_node(new_model, "Class", "LHS")
@@ -54,69 +60,37 @@ Element function ramify(model : Element):
 	instantiate_node(new_model, "Class", "NAC")
 	instantiate_link(new_model, "Inheritance", "", "NAC", "LHS_Root")
 
-	//	Class Pre_Element {
-	//		label : String {
-	//			target_lower_cardinality = 1
-	//			target_upper_cardinality = 1
-	//		}
-	//		constraint : funcdef {
-	//			target_upper_cardinality = 1
-	//		}
+	//	Class PreElement {
+	//		label : String
+	//		constraint? : ActionLanguage
 	//	}
-	instantiate_node(new_model, "Class", "Pre_Element")
-	instantiate_link(new_model, "Association", "Pre_Element_label", "Pre_Element", "String")
-	instantiate_attribute(new_model, "Pre_Element_label", "name", "label")
-	instantiate_attribute(new_model, "Pre_Element_label", "target_lower_cardinality", 1)
-	instantiate_attribute(new_model, "Pre_Element_label", "target_upper_cardinality", 1)
-	instantiate_link(new_model, "Association", "Pre_Element_constraint", "Pre_Element", "funcdef")
-	instantiate_attribute(new_model, "Pre_Element_constraint", "name", "constraint")
-	instantiate_attribute(new_model, "Pre_Element_constraint", "target_upper_cardinality", 1)
-
-	// Association LHS_contains (LHS_Root, Pre_Element) {}
-	instantiate_link(new_model, "Association", "LHS_contains", "LHS_Root", "Pre_Element")
-	instantiate_attribute(new_model, "LHS_contains", "name", "contains")
+	instantiate_node(new_model, "Class", "PreElement")
+	model_define_attribute(new_model, "PreElement", "label", False, "String")
+	model_define_attribute(new_model, "PreElement", "constraint", True, "ActionLanguage")
+
+	// Association LHS_contains (LHS_Root, PreElement) {}
+	instantiate_link(new_model, "Association", "LHS_contains", "LHS_Root", "PreElement")
 
 	//	Class RHS {
-	//		action : FuncDef {
-	//			target_upper_cardinality = 1
-	//		}
+	//		action? : ActionLanguage
 	//		upper_cardinality = 1
 	//		lower_cardinality = 1
 	//	}
 	instantiate_node(new_model, "Class", "RHS")
 	instantiate_attribute(new_model, "RHS", "lower_cardinality", 1)
 	instantiate_attribute(new_model, "RHS", "upper_cardinality", 1)
-	instantiate_link(new_model, "Association", "RHS_action", "RHS", "funcdef")
-	instantiate_attribute(new_model, "RHS_action", "name", "action")
-	instantiate_attribute(new_model, "RHS_action", "target_upper_cardinality", 1)
-
-	//	Class Post_Element {
-	//		label : String {
-	//			target_lower_cardinality = 1
-	//			target_upper_cardinality = 1
-	//		}
-	//		value : funcdef {
-	//			target_upper_cardinality = 1
-	//		}
-	//		action : funcdef {
-	//			target_upper_cardinality = 1
-	//		}
+	model_define_attribute(new_model, "RHS", "action", True, "ActionLanguage")
+
+	//	Class PostElement {
+	//		label : String
+	//		action? : ActionLanguage
 	//	}
-	instantiate_node(new_model, "Class", "Post_Element")
-	instantiate_link(new_model, "Association", "Post_Element_label", "Post_Element", "String")
-	instantiate_attribute(new_model, "Post_Element_label", "name", "label")
-	instantiate_attribute(new_model, "Post_Element_label", "target_lower_cardinality", 1)
-	instantiate_attribute(new_model, "Post_Element_label", "target_upper_cardinality", 1)
-	instantiate_link(new_model, "Association", "Post_Element_value", "Post_Element", "funcdef")
-	instantiate_attribute(new_model, "Post_Element_value", "name", "value")
-	instantiate_attribute(new_model, "Post_Element_value", "target_upper_cardinality", 1)
-	instantiate_link(new_model, "Association", "Post_Element_action", "Post_Element", "funcdef")
-	instantiate_attribute(new_model, "Post_Element_action", "name", "action")
-	instantiate_attribute(new_model, "Post_Element_action", "target_upper_cardinality", 1)
-
-	// Association RHS_contains (RHS, Post_Element) {}
-	instantiate_link(new_model, "Association", "RHS_contains", "RHS", "Post_Element")
-	instantiate_attribute(new_model, "RHS_contains", "name", "contains")
+	instantiate_node(new_model, "Class", "PostElement")
+	model_define_attribute(new_model, "PostElement", "label", False, "String")
+	model_define_attribute(new_model, "PostElement", "action", True, "ActionLanguage")
+
+	// Association RHS_contains (RHS, PostElement) {}
+	instantiate_link(new_model, "Association", "RHS_contains", "RHS", "PostElement")
 
 	// Basics are added, now we need to add each node and transition, but slightly modified
 	Element keys
@@ -124,15 +98,27 @@ Element function ramify(model : Element):
 	Element new_entry
 	Element entry
 
-	keys = dict_keys(old_m)
+	keys = set_to_list(dict_keys(old_m))
 	String type_name
 	String old_source
 	String old_target
-	Element to_link
-	to_link = create_node()
+	String attr_name
+	Element masked_attributes
+	Element copied_attributes
+
+	masked_attributes = create_node()
+	set_add(masked_attributes, "constraint")
+	set_add(masked_attributes, "lower_cardinality")
+	set_add(masked_attributes, "source_lower_cardinality")
+	set_add(masked_attributes, "target_lower_cardinality")
+
+	copied_attributes = create_node()
+	set_add(copied_attributes, "upper_cardinality")
+	set_add(copied_attributes, "source_upper_cardinality")
+	set_add(copied_attributes, "target_upper_cardinality")
 
 	while (read_nr_out(keys) > 0):
-		key = set_pop(keys)
+		key = list_pop(keys, 0)
 		entry = old_m[key]
 
 		type_name = read_type(model, key)
@@ -141,48 +127,64 @@ Element function ramify(model : Element):
 			instantiate_node(new_model, type_name, "Post_" + key)
 
 			// Also make it inherit from the "root element"
-			instantiate_link(new_model, "Inheritance", "", "Pre_" + key, "Pre_Element")
-			instantiate_link(new_model, "Inheritance", "", "Post_" + key, "Post_Element")
+			instantiate_link(new_model, "Inheritance", "", "Pre_" + key, "PreElement")
+			instantiate_link(new_model, "Inheritance", "", "Post_" + key, "PostElement")
+
+		elif (type_name == "AttributeLink"):
+			// Got an attribute, so find out the source and name
+			old_source = reverseKeyLookup(model["model"], read_edge_src(entry))
+			attr_name = read_attribute(model, key, "name")
+
+			// TODO distinguish between Simple and Complex Attributes
+
+			if (dict_in(new_model["model"], "Pre_" + old_source)):
+				// Only if it is a class that it originates from is a class, should we add this
+				if (is_nominal_instance(model, old_source, "Element")):
+					// If the attribute is one used in the conformance check, we should mask it
+					// Add the attribute in the new model, altering its name and making it optional
+					model_define_attribute(new_model, "Pre_" + old_source, "constraint_" + attr_name, True, "ActionLanguage")
+					model_define_attribute(new_model, "Post_" + old_source, "value_" + attr_name, True, "ActionLanguage")
+			else:
+				// Queue for later
+				list_append(keys, key)
 
 		elif (type_name == "Association"):
 			old_source = reverseKeyLookup(model["model"], read_edge_src(entry))
 			old_target = reverseKeyLookup(model["model"], read_edge_dst(entry))
-			instantiate_link(new_model, type_name, "Pre_" + key, "Pre_" + old_source, "Pre_" + old_target)
-			instantiate_link(new_model, type_name, "Post_" + key, "Post_" + old_source, "Post_" + old_target)
 
-			// 1) Make it inherit from the Root Element (Pre_Element or Post_Element)
-			instantiate_link(new_model, "Inheritance", "", "Pre_" + key, "Pre_Element")
-			instantiate_link(new_model, "Inheritance", "", "Post_" + key, "Post_Element")
-			
+			if (bool_and(dict_in(new_model["model"], "Pre_" + old_source), dict_in(new_model["model"], "Pre_" + old_target))):
+				instantiate_link(new_model, type_name, "Pre_" + key, "Pre_" + old_source, "Pre_" + old_target)
+				instantiate_link(new_model, type_name, "Post_" + key, "Post_" + old_source, "Post_" + old_target)
+
+				// Make it inherit from the Root Element (PreElement or PostElement)
+				instantiate_link(new_model, "Inheritance", "", "Pre_" + key, "PreElement")
+				instantiate_link(new_model, "Inheritance", "", "Post_" + key, "PostElement")
+			else:
+				// Queue for later
+				list_append(keys, key)
+				
 		elif (type_name == "Inheritance"):
 			old_source = reverseKeyLookup(model["model"], read_edge_src(entry))
 			old_target = reverseKeyLookup(model["model"], read_edge_dst(entry))
-			instantiate_link(new_model, type_name, "Pre_" + key, "Pre_" + old_source, "Pre_" + old_target)
-			instantiate_link(new_model, type_name, "Post_" + key, "Post_" + old_source, "Post_" + old_target)
 
-		elif (bool_not(has_value(entry))):
-			create_edge(to_link, entry)
-
-	while (read_nr_out(to_link) > 0):
-		entry = set_pop(to_link)
-		type_name = read_type(model, reverseKeyLookup(model["model"], entry))
-		// Primitive values themselves are not copied, so skip that here
-
-		// An instance link, so just copy over (don't make element of Root Element), and don't even copy if it is lower cardinality
-		// It is probably an attribute at the meta-language level, so check which one it is
-		String name
-		name = read_attribute(model["metamodel"], type_name, "name")
-		if (bool_not(bool_or(bool_or(name == "lower_cardinality", name == "source_lower_cardinality"), bool_or(name == "constraint", name == "target_lower_cardinality")))):
-			// Not a lower cardinality or constraint, so copy
-			old_source = reverseKeyLookup(model["model"], read_edge_src(entry))
-			if (bool_or(bool_or(name == "name", name == "upper_cardinality"), bool_or(name == "source_upper_cardinality", name == "target_upper_cardinality"))):
-				// Keep the old name for the physical attributes!
-				instantiate_attribute(new_model, "Pre_" + old_source, name, read_edge_dst(entry))
-				instantiate_attribute(new_model, "Post_" + old_source, name, read_edge_dst(entry))
+			if (bool_and(dict_in(new_model["model"], "Pre_" + old_source), dict_in(new_model["model"], "Pre_" + old_target))):
+				instantiate_link(new_model, type_name, "Pre_" + key, "Pre_" + old_source, "Pre_" + old_target)
+				instantiate_link(new_model, type_name, "Post_" + key, "Post_" + old_source, "Post_" + old_target)
 			else:
-				// Rename the attributes as well
-				instantiate_attribute(new_model, "Pre_" + old_source, "Pre_" + name, read_edge_dst(entry))
-				instantiate_attribute(new_model, "Post_" + old_source, "Post_" + name, read_edge_dst(entry))
+				// Queue for later
+				list_append(keys, key)
+
+		elif (bool_not(has_value(entry))):
+			type_name = read_type(model, key)
+			// Primitive values themselves are not copied, so skip that here
+
+			attr_name = read_attribute(model, type_name, "name")
+			if (is_nominal_instance(model["metamodel"], type_name, "Attribute")):
+				old_source = reverseKeyLookup(model["model"], read_edge_src(entry))
+
+				if (set_in(copied_attributes, attr_name)):
+					instantiate_attribute(new_model, "Pre_" + old_source, attr_name, read_attribute(model, old_source, attr_name))
+					instantiate_attribute(new_model, "Post_" + old_source, attr_name, read_attribute(model, old_source, attr_name))
 
 	// Define schedule over these elements
 

+ 92 - 25
bootstrap/transform.alc

@@ -72,7 +72,7 @@ Element function get_possible_bindings(host_model : Element, schedule_model : El
 
 	typename = read_type(schedule_model, current_element)
 	original_typename = string_substr(typename, 4, string_len(typename))
-
+	
 	if (is_edge(schedule_model["model"][current_element])):
 		// 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")
@@ -93,17 +93,15 @@ Element function get_possible_bindings(host_model : Element, schedule_model : El
 
 		else:
 			// Neither is bound, so just get all of them
-			log("ERROR: unbound source/target for association!")
-			//TODO should actually return all
-			return create_node()!
+			return 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
 
-		ic = allIncomingAssociationInstances(schedule_model, current_element, "Pre_Element")
-		oc = allOutgoingAssociationInstances(schedule_model, current_element, "Pre_Element")
+		ic = allIncomingAssociationInstances(schedule_model, current_element, "PreElement")
+		oc = allOutgoingAssociationInstances(schedule_model, current_element, "PreElement")
 
 		while (bool_and(read_nr_out(ic) > 0, read_nr_out(options) == 0)):
 			poll = set_pop(ic)
@@ -122,6 +120,7 @@ Element function get_possible_bindings(host_model : Element, schedule_model : El
 			options = allInstances(host_model, original_typename)
 		elif (read_nr_out(options) > 1):
 			// Multiple "only" options, which will not work out: no options!
+			log("    multi!")
 			return create_node()!
 
 	// Filter options further
@@ -143,13 +142,56 @@ Element function get_possible_bindings(host_model : Element, schedule_model : El
 			else:
 				// Check local constraints and add only if positive
 				Element constraint_function
-				constraint_function = read_attribute(schedule_model, current_element, "constraint")
 				Boolean result
-				result = constraint_function(host_model, option)
+				Element func
+
+				constraint_function = read_attribute(schedule_model, current_element, "constraint")
+				func = get_func_AL_model(constraint_function)
+				result = func(host_model, option)
+
 				if (result):
 					set_add(filtered_options, option)
 
-	return filtered_options!
+	Element attributes
+	String attribute
+	Element value
+	Element func
+	Boolean result
+	Element attributes_copy
+
+	options = filtered_options
+	filtered_options = create_node()
+
+	// Check whether all attributes have a satisfied condition
+	attributes_copy = dict_keys(getAttributeList(schedule_model, current_element))
+
+	while (read_nr_out(options) > 0):
+		option = set_pop(options)
+		attributes = set_copy(attributes_copy)
+
+		result = True
+		while (read_nr_out(attributes) > 0):
+			attribute = set_pop(attributes)
+			if (bool_not(string_startswith(attribute, "constraint_"))):
+				continue!
+
+			value = read_attribute(schedule_model, current_element, attribute)
+			// Attribute might be undefined, so skip if it is
+			if (element_neq(value, read_root())):
+				func = get_func_AL_model(value)
+				result = func(read_attribute(host_model, option, string_substr(attribute, string_len("constraint_"), string_len(attribute) + 1)))
+			else:
+				result = True
+
+			if (bool_not(result)):
+				break!
+
+		// Check value of last result, which will be True if all passed, or False otherwise
+		if (result):
+			set_add(filtered_options, option)
+
+	options = filtered_options
+	return options!
 
 Element function full_match(host_model : Element, schedule_model : Element, current : String):
 	Element NACs
@@ -225,14 +267,19 @@ Element function match(host_model : Element, schedule_model : Element, LHS : Str
 		mappings = new_mappings
 
 	// Finished, so try the global constraint
-	Element constraint
+	String constraint
+	Element func
+	Boolean result
 
 	new_mappings = create_node()
 	constraint = read_attribute(schedule_model, LHS, "constraint")
 	if (element_neq(constraint, read_root())):
 		while (read_nr_out(mappings) > 0):
 			map = set_pop(mappings)
-			if (constraint(host_model, map)):
+			func = get_func_AL_model(constraint)
+			result = func(host_model, map)
+
+			if (result):
 				set_add(new_mappings, map)
 		mappings = new_mappings
 
@@ -257,7 +304,6 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 	Element RHS_map
 	String tmp
 	Element value
-	Element value_function
 	Element action
 	Element original_RHS_labels
 
@@ -287,17 +333,7 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 	while (read_nr_out(labels_to_add) > 0):
 		// Add the elements linked to these labels
 		label = list_pop(labels_to_add, 0)
-		if (element_neq(read_attribute(schedule_model, RHS_map[label], "value"), read_root())):
-			// There is a value associated with this node
-			value_function = read_attribute(schedule_model, RHS_map[label], "value")
-			value = value_function(host_model, mapping)
-
-			typename = read_type(schedule_model, RHS_map[label])
-			original_typename = string_substr(typename, 5, string_len(typename))
-			new_name = instantiate_value(host_model, original_typename, "", value)
-			dict_add(new_mapping, label, new_name)
-
-		elif (is_edge(schedule_model["model"][RHS_map[label]])):
+		if (is_edge(schedule_model["model"][RHS_map[label]])):
 			// Edge
 			src = read_attribute(schedule_model, reverseKeyLookup(schedule_model["model"], read_edge_src(schedule_model["model"][RHS_map[label]])), "label")
 			dst = read_attribute(schedule_model, reverseKeyLookup(schedule_model["model"], read_edge_dst(schedule_model["model"][RHS_map[label]])), "label")
@@ -319,11 +355,40 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 			new_name = instantiate_node(host_model, original_typename, "")
 			dict_add(new_mapping, label, new_name)
 
+	Element attributes
+	String attribute
+	Element result
+	Element func
+
 	while (read_nr_out(original_RHS_labels) > 0):
+		// Perform actions
 		label = set_pop(original_RHS_labels)
+
+		// Do all attribute actions that are defined
+		attributes = dict_keys(getAttributeList(schedule_model, RHS_map[label]))
+		while (read_nr_out(attributes) > 0):
+			attribute = set_pop(attributes)
+			if (bool_not(string_startswith(attribute, "value_"))):
+				continue!
+
+			value = read_attribute(schedule_model, RHS_map[label], attribute)
+			if (element_neq(value, read_root())):
+				func = get_func_AL_model(value)
+				result = func(host_model, new_mapping[label], mapping)
+
+				if (has_value(result)):
+					// New value defined, so assign!
+					instantiate_attribute(host_model, new_mapping[label], string_substr(attribute, string_len("value_"), string_len(attribute) + 1), result)
+				else:
+					// Non-value return means to destroy the attribute!
+					unset_attribute(host_model, new_mapping[label], string_substr(attribute, string_len("value_"), string_len(attribute) + 1))
+
+		// Do the global action of each element
 		action = read_attribute(schedule_model, RHS_map[label], "action")
 		if (element_neq(action, read_root())):
-			action(host_model, new_mapping[label], mapping)
+			Element func
+			func = get_func_AL_model(action)
+			func(host_model, new_mapping[label], mapping)
 
 	while (read_nr_out(labels_to_remove) > 0):
 		// Remove the elements linked to these labels
@@ -334,7 +399,9 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 	// Execute global action (whatever it may be)
 	action = read_attribute(schedule_model, RHS, "action")
 	if (element_neq(action, read_root())):
-		action(host_model, new_mapping)
+		Element func
+		func = get_func_AL_model(action)
+		func(host_model, new_mapping)
 
 	return!
 

+ 12 - 3
core/core_algorithm.alc

@@ -13,7 +13,8 @@ include "metamodels.alh"
 Element core = ?
 
 String core_location = "models/CoreFormalism"
-String core_model_location = "models/core"
+String core_model_location = "core"
+String coreM_model_location = "models/core"
 
 Void function main():
 	// Initialize the Core Formalism
@@ -34,7 +35,8 @@ Void function main():
 	// Create the Model itself and make public
 	core_formalism = import_node(core_location)
 	core = instantiate_model(core_formalism)
-	export_node(core_model_location, core["model"])
+	export_node(core_model_location, core)
+	export_node(coreM_model_location, core["model"])
 
 	// Switch all new users to the user_function
 	// This accesses the bootstrap level, so do not change this unless you know what you are doing
@@ -107,7 +109,7 @@ Void function main():
 	// Add the core model
 	core_model = instantiate_node(core, "Model", "")
 	instantiate_attribute(core, core_model, "name", "core")
-	instantiate_attribute(core, core_model, "location", core_model_location)
+	instantiate_attribute(core, core_model, "location", coreM_model_location)
 	instantiate_attribute(core, core_model, "permissions", "200")
 	instance_of = instantiate_link(core, "instanceOf", "", core_model, core_formalism_model)
 	instantiate_attribute(core, instance_of, "type_mapping", core["type_mapping"])
@@ -322,6 +324,7 @@ String function get_user_id(name : String):
 	String user
 
 	users = allInstances(core, "User")
+
 	while (read_nr_out(users) > 0):
 		user = set_pop(users)
 		if (value_eq(read_attribute(core, user, "name"), name)):
@@ -591,6 +594,7 @@ Void function user_function_skip_init(user_id : String):
 
 								// 3) Transform
 
+								log("EXECUTE TRANSFORMATION " + cast_e2s(read_attribute(core, transformation_id, "name")))
 								result = transform(merged_model, schedule_model)
 								output("Transformation executed with result: " + cast_v2s(result))
 
@@ -724,6 +728,7 @@ Void function user_function_skip_init(user_id : String):
 			String new_model_id
 
 			old_type_id = ""
+			log("Adding MT language")
 
 			// Read involved formalisms
 			all_formalisms = create_node()
@@ -758,7 +763,9 @@ Void function user_function_skip_init(user_id : String):
 					String tracability_link
 
 					// New location is available, so write
+					log("FUSE")
 					merged_formalism = model_fuse(set_copy(all_formalisms))
+					log("Fuse OK")
 					model_create(merged_formalism, "__merged_" + name, user_id, type_id, "Model")
 					merged_formalism_id = get_model_id("__merged_" + name)
 
@@ -769,7 +776,9 @@ Void function user_function_skip_init(user_id : String):
 						instantiate_attribute(core, tracability_link, "type", "merged")
 
 					// Merge complete, now RAMify!
+					log("RAM")
 					ramified_formalism = ramify(merged_formalism)
+					log("RAMed")
 					model_create(ramified_formalism, name, user_id, type_id, "Model")
 					ramified_formalism_id = get_model_id(name)
 

+ 52 - 45
core/core_formalism.mvc

@@ -2,59 +2,66 @@ import models/SimpleClassDiagrams as SimpleClassDiagrams
 include "primitives.alh"
 
 SimpleClassDiagrams CoreFormalism {
-    Class String {
-        $
-            if (bool_not(is_physical_string(self))):
-                return "String has no string value"!
-            else:
-                return "OK"!
-        $
+    SimpleAttribute String {
+        constraint = $
+            String function constraint(model : Element, name : String):
+                if (bool_not(is_physical_string(model["model"][name]))):
+                    return "String has no string value"!
+                else:
+                    return "OK"!
+            $
     }
 
-    Class Permissions {
-        $
-            if (bool_not(is_physical_string(self))):
-                return "Permissions has no string value"!
-            else:
-                return "OK"!
-        $
+    SimpleAttribute Permissions {
+        constraint = $
+            String function constraint(model : Element, name : String):
+                if (bool_not(is_physical_string(model["model"][name]))):
+                    return "Permissions has no string value"!
+                else:
+                    return "OK"!
+            $
     }
 
-    Class Boolean {
-        $
-            if (bool_not(is_physical_boolean(self))):
-                return "Boolean has no bool value"!
-            else:
-                return "OK"!
-        $
+    SimpleAttribute Boolean {
+        constraint = $
+            String function constraint(model : Element, name : String):
+                if (bool_not(is_physical_boolean(model["model"][name]))):
+                    return "Boolean has no bool value"!
+                else:
+                    return "OK"!
+            $
     }
 
-    Class Natural {
-        $
-            if (bool_not(is_physical_int(self))):
-                return "Natural has no integer value"!
-            elif (integer_lt(self, 0)):
-                return "Natural has negative value"!
-            else:
-                return "OK"!
-        $
+    SimpleAttribute Natural {
+        constraint = $
+            String function constraint(model : Element, name : String):
+                if (bool_not(is_physical_int(model["model"][name]))):
+                    return "Natural has no integer value"!
+                elif (integer_lt(model["model"][name], 0)):
+                    return "Natural has negative value"!
+                else:
+                    return "OK"!
+            $
     }
 
-    Class TypeMapping {
-        $
-            if (has_value(self)):
-                return "TypeMapping cannot have a value for root node!"!
-            Element keys
-            String key
-            keys = dict_keys(self)
-            while (read_nr_out(keys) > 0):
-                key = set_pop(keys)
-                if (bool_not(is_physical_string(key))):
-                    return ("Key on type mapping is not a string: " + cast_e2s(key))!
-                elif (bool_not(is_physical_string(self[key]))):
-                    return ("Value on type mapping is not a string for key " + cast_e2s(key))!
-            return "OK"!
-        $
+    SimpleAttribute TypeMapping {
+        constraint = $
+            String function constraint(model : Element, name : String):
+                Element self
+                self = model["model"][name]
+                if (has_value(self)):
+                    return "TypeMapping cannot have a value for root node!"!
+                Element keys
+                String key
+                keys = dict_keys(self)
+                while (read_nr_out(keys) > 0):
+                    key = set_pop(keys)
+                    if (bool_not(is_physical_string(key))):
+                        return ("Key on type mapping is not a string: " + cast_e2s(key))!
+                    elif (bool_not(is_physical_string(self[key]))):
+                        return ("Value on type mapping is not a string for key " + cast_e2s(key))!
+                return "OK"!
+            $
     }
 
     Class User {

+ 38 - 36
core/mini_modify.alc

@@ -27,23 +27,24 @@ Element function modify(model : Element, write : Boolean):
 			output("Allowed operations:")
 			if (write):
 				output(" == READ/WRITE ==")
-				output("  instantiate -- Create a new model element")
-				output("  delete      -- Delete an existing element")
-				output("  attr_add    -- Add an attribute to an element")
-				output("  attr_del    -- Delete an attribute of an element")
-				output("  attr_modify -- Modify an attribute of an element")
-				output("  constrain   -- Add a constraint function to the model")
-				output("  rename      -- Rename an existing element")
-				output("  modify      -- Modify the attributes of an element")
-				output("  retype      -- Change the type of an element")
+				output("  instantiate   -- Create a new model element")
+				output("  delete        -- Delete an existing element")
+				output("  attr_add      -- Add an attribute to an element")
+				output("  attr_add_code -- Add a coded attribute to an element")
+				output("  attr_del      -- Delete an attribute of an element")
+				output("  attr_modify   -- Modify an attribute of an element")
+				output("  constrain     -- Add a constraint function to the model")
+				output("  rename        -- Rename an existing element")
+				output("  modify        -- Modify the attributes of an element")
+				output("  retype        -- Change the type of an element")
 			else:
 				output(" == READ-ONLY ==")
-			output("  list        -- Prints the list of elements in the model")
-			output("  list_full   -- Prints the list of all elements in the model")
-			output("  types       -- Prints the list of elements that can be instantiated")
-			output("  read        -- Prints the current state of a model element")
-			output("  verify      -- Check whether the model conforms to the metamodel")
-			output("  exit        -- Leave the modification interface")
+			output("  list          -- Prints the list of elements in the model")
+			output("  list_full     -- Prints the list of all elements in the model")
+			output("  types         -- Prints the list of elements that can be instantiated")
+			output("  read          -- Prints the current state of a model element")
+			output("  verify        -- Check whether the model conforms to the metamodel")
+			output("  exit          -- Leave the modification interface")
 		elif (cmd == "exit"):
 			return model!
 		elif (cmd == "instantiate"):
@@ -82,27 +83,6 @@ Element function modify(model : Element, write : Boolean):
 			else:
 				output("Permission denied")
 
-		elif (cmd == "constrain"):
-			if (write):
-				output("Element to constrain (empty for global)?")
-				String model_name
-				model_name = input()
-
-				if (model_name == ""):
-					// Global constraint
-					output("Give input to function constructors for GLOBAL constraint!")
-					set_model_constraints(model, construct_function())
-				elif (dict_in(model["model"], model_name)):
-					// Local constraint for this model
-					output("Give input to function constructors for LOCAL constraint!")
-					add_constraint(model, model_name, construct_function())
-					output("Added constraint to model!")
-				else:
-					// Local constraint, but model not found
-					output("Unknown model; aborting")
-			else:
-				output("Permission denied")
-
 		elif (cmd == "attr_modify"):
 			if (write):
 				String model_name
@@ -148,6 +128,28 @@ Element function modify(model : Element, write : Boolean):
 			else:
 				output("Permission denied")
 
+		elif (cmd == "attr_add_code"):
+			if (write):
+				String model_name
+				output("Which model do you want to assign a coded attribute to?")
+				model_name = input()
+				if (dict_in(model["model"], model_name)):
+					Element attrs
+					attrs = getAttributeList(model, model_name)
+					String attr_name
+					output("Which attribute do you wish to assign?")
+					attr_name = input()
+					if (set_in(dict_keys(attrs), attr_name)):
+						output("Waiting for code constructors...")
+						instantiate_attribute_code(model, model_name, attr_name, input())
+						output("Added attribute!")
+					else:
+						output("No such attribute!")
+				else:
+					output("No such model!")
+			else:
+				output("Permission denied")
+
 		elif (cmd == "attr_del"):
 			if (write):
 				String model_name

+ 18 - 22
integration/code/cbd_design.mvc

@@ -2,32 +2,31 @@ import models/SimpleClassDiagrams as SCD
 include "primitives.alh"
 
 SCD CausalBlockDiagrams_Design{
-    Class Float {
-        $
-            if (bool_not(is_physical_float(self))):
-                return "Float has no float value"!
-            else:
-                return "OK"!
-        $
+    AttributeValue Float {
+        constraint = $
+            String constraint(model : Element, name : String):
+                if (bool_not(is_physical_float(model["model"][name]))):
+                    return "Float has no float value"!
+                else:
+                    return "OK"!
+            $
     }
 
-    Class String {
-        $
-            if (bool_not(is_physical_string(self))):
-                return "String has no string value"!
-            else:
-                return "OK"!
-        $
+    AttributeValue String {
+        constraint = $
+            String constraint(model : Element, name : String):
+                if (bool_not(is_physical_string(model["model"][name]))):
+                    return "String has no string value"!
+                else:
+                    return "OK"!
+            $
     }
 
     Class Block{}
     Class ICBlock{}
 
     Class ConstantBlock{
-        value : Float {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-        }
+        value : Float
     }
 
     Class AdditionBlock{}
@@ -38,10 +37,7 @@ SCD CausalBlockDiagrams_Design{
     Class IntegratorBlock{}
     Class DerivatorBlock{}
     Class ProbeBlock{
-        name : String {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-        }
+        name : String
     }
 
     Association Link(Block, Block){}

+ 23 - 43
integration/code/cbd_runtime.mvc

@@ -2,49 +2,39 @@ import models/SimpleClassDiagrams as SCD
 include "primitives.alh"
 
 SCD CausalBlockDiagrams_Runtime{
-    Class Float {
-        $
-            if (bool_not(is_physical_float(self))):
-                return "Float has no float value"!
-            else:
-                return "OK"!
-        $
+    AttributeValue Float {
+        constraint = $
+            String constraint(model : Element, name : String):
+                if (bool_not(is_physical_float(model["model"][name]))):
+                    return "Float has no float value"!
+                else:
+                    return "OK"!
+            $
     }
 
-    Class String {
-        $
-            if (bool_not(is_physical_string(self))):
-                return "String has no string value"!
-            else:
-                return "OK"!
-        $
+    AttributeValue String {
+        constraint = $
+            String constraint(model : Element, name : String):
+                if (bool_not(is_physical_string(model["model"][name]))):
+                    return "String has no string value"!
+                else:
+                    return "OK"!
+            $
     }
 
     Class Block{
-        signal : Float {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-        }
+        signal : Float
     }
     Class ICBlock{
-        last_in : Float {
-            target_lower_cardinality = 0
-            target_upper_cardinality = 1
-        }
+        last_in : Float
     }
 
     Class ConstantBlock{
-        value : Float {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-        }
+        value : Float
     }
 
     Class ProbeBlock{
-        name : String {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-        }
+        name : String
     }
 
     Class AdditionBlock{}
@@ -53,10 +43,7 @@ SCD CausalBlockDiagrams_Runtime{
     Class InverseBlock{}
     Class DelayBlock{}
     Class IntegratorBlock{
-        last_out : Float {
-            target_lower_cardinality = 0
-            target_upper_cardinality = 1
-        }
+        last_out? : Float
     }
 
     Class DerivatorBlock{}
@@ -64,15 +51,8 @@ SCD CausalBlockDiagrams_Runtime{
         lower_cardinality = 1
         upper_cardinality = 1
 
-        start_time : Float {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-        }
-
-        current_time : Float {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-        }
+        start_time : Float
+        current_time : Float
     }
 
     Association Link(Block, Block){

+ 11 - 19
integration/code/fsa_design.mvc

@@ -2,20 +2,18 @@ import models/SimpleClassDiagrams as SCD
 include "primitives.alh"
 
 SCD FiniteStateAutomata_Design{
-    Class String {
-        $
-            if (bool_not(is_physical_string(self))):
-                return "String has no string value"!
-            else:
-                return "OK"!
-        $
+    AttributeValue String {
+        constraint = $
+            String constraint(model : Element, name : String):
+                if (bool_not(is_physical_string(model["model"][name]))):
+                    return "String has no string value"!
+                else:
+                    return "OK"!
+            $
     }
 
     Class State {
-        name : String {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-        }
+        name : String
     }
 
     Class InitialState {
@@ -24,14 +22,8 @@ SCD FiniteStateAutomata_Design{
     }
 
     Association Transition (State, State) {
-        event : String {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-        }
-
-        raise : String {
-            target_upper_cardinality = 1
-        }
+        event : String
+        raise? : String
     }
 
     Inheritance (InitialState, State){}

+ 11 - 19
integration/code/fsa_runtime.mvc

@@ -2,20 +2,18 @@ import models/SimpleClassDiagrams as SCD
 include "primitives.alh"
 
 SCD FiniteStateAutomata_Runtime{
-    Class String {
-        $
-            if (bool_not(is_physical_string(self))):
-                return "String has no string value"!
-            else:
-                return "OK"!
-        $
+    AttributeValue String {
+        constraint = $
+            String constraint(model : Element, name : String):
+                if (bool_not(is_physical_string(model["model"][name]))):
+                    return "String has no string value"!
+                else:
+                    return "OK"!
+            $
     }
 
     Class State {
-        name : String {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-        }
+        name : String
     }
 
     Class InitialState {
@@ -24,14 +22,8 @@ SCD FiniteStateAutomata_Runtime{
     }
 
     Association Transition (State, State){
-        event : String {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-        }
-
-        raise : String {
-            target_upper_cardinality = 1
-        }
+        event : String
+        raise? : String
     }
 
     Inheritance (InitialState, State){}

+ 1 - 2
integration/code/my_petrinet_with_MM.mvc

@@ -1,8 +1,7 @@
 import models/SimpleClassDiagrams as SCD
-include "primitives.alh"
 
 SCD PetriNets{
-    Class Natural {}
+    AttributeValue Natural {}
     Class Place{
         tokens : Natural
     }

+ 14 - 9
integration/code/my_petrinet_with_MM_and_constraints.mvc

@@ -2,15 +2,20 @@ import models/SimpleClassDiagrams as SCD
 include "primitives.alh"
 
 SCD PetriNets{
-    Class Natural {
-        $
-            if (bool_not(is_physical_int(self))):
-                return "Natural has no integer value"!
-            elif (integer_lt(self, 0)):
-                return "Natural does not have a positive or zero value"!
-            else:
-                return "OK"!
-         $
+    SimpleAttribute Natural {
+        constraint =
+            $
+            String function constraint_Natural(model : Element, name : String):
+                Element self
+                self = model["model"][name]
+                if (is_physical_int(self)):
+                    if (integer_gte(self, 0)):
+                        return "OK"!
+                    else:
+                        return "Natural number not larger than or equal to zero"!
+                else:
+                    return "Natural number not larger than or equal to zero"!
+            $
     }
     Class Place{
         tokens : Natural

+ 2 - 1
integration/code/petrinets.mvc

@@ -1,7 +1,8 @@
 import models/SimpleClassDiagrams as SimpleClassDiagrams
 
 SimpleClassDiagrams PetriNets{
-    Class Natural {}
+    SimpleAttribute Natural {}
+
     Class Place{
         tokens : Natural
     }

+ 18 - 9
integration/code/petrinets_constraints.mvc

@@ -2,23 +2,32 @@ import models/SimpleClassDiagrams as SCD
 include "primitives.alh"
 
 SCD PetriNets{
-    Class Natural {
-        $
-            if (bool_not(is_physical_int(self))):
-                return "Natural has no integer value"!
-            elif (integer_lt(self, 0)):
-                return "Natural does not have a positive or zero value"!
-            else:
-                return "OK"!
-         $
+    SimpleAttribute Natural {
+        constraint =
+            $
+            String function constraint_Natural(model : Element, name : String):
+                Element self
+                self = model["model"][name]
+                if (is_physical_int(self)):
+                    if (integer_gte(self, 0)):
+                        return "OK"!
+                    else:
+                        return "Natural number not larger than or equal to zero"!
+                else:
+                    return "Natural number not larger than or equal to zero"!
+            $
     }
+
     Class Place{
         tokens : Natural
     }
+
     Class Transition{}
+
     Association P2T (Place, Transition) {
         weight : Natural
     }
+
     Association T2P (Transition, Place) {
         weight : Natural
     }

+ 2 - 2
integration/code/pn_design.mvc

@@ -1,8 +1,8 @@
 import models/SimpleClassDiagrams as SimpleClassDiagrams
 
 SimpleClassDiagrams PetriNets_Design{
-    Class Natural {}
-    Class String {}
+    SimpleAttribute Natural {}
+    SimpleAttribute String {}
 
     Class Place {
         tokens : Natural

+ 18 - 25
integration/code/pn_design_to_runtime.mvc

@@ -1,4 +1,6 @@
 import models/RAM_PetriNets_Design_Runtime as RAM_PN_DR
+include "primitives.alh"
+include "modelling.alh"
 
 RAM_PN_DR annotate {
     Composite schedule {
@@ -16,12 +18,9 @@ RAM_PN_DR annotate {
                 }
                 Post_PetriNets_Runtime/Transition ct2 {
                     label = "1"
-                    action = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Void function action(host_model : Element, name : String, mapping : Element):
-                            instantiate_attribute(host_model, name, "executing", False)
-                            return!
+                    value_executing = $
+                        Boolean function value(model : Element, name : String, mapping : Element):
+                            return True!
                         $
                 }
                 Post_D2R_TransitionLink (ct1, ct2){
@@ -41,13 +40,13 @@ RAM_PN_DR annotate {
                 }
                 Post_PetriNets_Runtime/Place cp2 {
                     label = "1"
-                    action = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Void function action(host_model : Element, name : String, mapping : Element):
-                            instantiate_attribute(host_model, name, "tokens", read_attribute(host_model, mapping["0"], "tokens"))
-                            instantiate_attribute(host_model, name, "name", read_attribute(host_model, mapping["0"], "name"))
-                            return!
+                    value_tokens = $
+                        Integer function value(model : Element, name : String, mapping : Element):
+                            return read_attribute(model, mapping["0"], "tokens")!
+                        $
+                    value_name = $
+                        Integer function value(model : Element, name : String, mapping : Element):
+                            return read_attribute(model, mapping["0"], "name")!
                         $
                 }
                 Post_D2R_PlaceLink (cp1, cp2){
@@ -103,12 +102,9 @@ RAM_PN_DR annotate {
                 }
                 Post_PetriNets_Runtime/P2T rhs_cp2t_p2t2(rhs_cp2t_p2, rhs_cp2t_t2) {
                     label = "7"
-                    action = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Void function action(host_model : Element, name : String, mapping : Element):
-                            instantiate_attribute(host_model, name, "weight", read_attribute(host_model, mapping["2"], "weight"))
-                            return!
+                    value_weight = $
+                        Integer function value(host_model : Element, name : String, mapping : Element):
+                            return read_attribute(host_model, mapping["2"], "weight")!
                         $
                 }
             }
@@ -161,12 +157,9 @@ RAM_PN_DR annotate {
                 }
                 Post_PetriNets_Runtime/T2P (rhs_ct2p_t2, rhs_ct2p_p2) {
                     label = "7"
-                    action = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Void function action(host_model : Element, name : String, mapping : Element):
-                            instantiate_attribute(host_model, name, "weight", read_attribute(host_model, mapping["2"], "weight"))
-                            return!
+                    value_weight = $
+                        Integer function value(host_model : Element, name : String, mapping : Element):
+                            return read_attribute(host_model, mapping["2"], "weight")!
                         $
                 }
             }

+ 4 - 4
integration/code/pn_print.mvc

@@ -1,4 +1,6 @@
 import models/RAM_PetriNets_Runtime as RAM_PN_R
+include "primitives.alh"
+include "modelling.alh"
 
 RAM_PN_R print {
     Composite schedule {
@@ -13,10 +15,8 @@ RAM_PN_R print {
                 Post_PetriNets/Place {
                     label = "0"
                     action = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Void function action(host_model : Element, name : String, mapping : Element):
-                            output((cast_v2s(read_attribute(host_model, name, "name")) + " --> ") + cast_v2s(read_attribute(host_model, name, "tokens")))
+                        Void function action(model : Element, name : String, mapping : Element):
+                            output((cast_v2s(read_attribute(model, name, "name")) + " --> ") + cast_v2s(read_attribute(model, name, "tokens")))
                             return!
                         $
                 }

+ 0 - 27
integration/code/pn_print_MR.mvc

@@ -1,27 +0,0 @@
-RAM_PN_R print {
-    Composite schedule {
-        {Contains} Success success {}
-        {Contains} ForAll print_tokens {
-            LHS {
-                Pre_PetriNets_Place {
-                    label = "0"
-                }
-            }
-            RHS {
-                Post_PetriNets_Place {
-                    label = "0"
-                    action = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Void function action(host_model : Element, name : String, mapping : Element):
-                            output((cast_v2s(read_attribute(host_model, name, "name")) + " --> ") + cast_v2s(read_attribute(host_model, name, "tokens")))
-                            return!
-                        $
-                }
-            }
-        }
-    }
-    OnSuccess (print_tokens, success) {}
-    OnFailure (print_tokens, success) {}
-    Initial (schedule, print_tokens) {}
-}

+ 3 - 3
integration/code/pn_runtime.mvc

@@ -1,9 +1,9 @@
 import models/SimpleClassDiagrams as SimpleClassDiagrams
 
 SimpleClassDiagrams PetriNets_Runtime{
-    Class Natural {}
-    Class Boolean {}
-    Class String {}
+    SimpleAttribute Natural {}
+    SimpleAttribute Boolean {}
+    SimpleAttribute String {}
 
     Class Place {
         tokens : Natural

+ 0 - 19
integration/code/pn_runtime_MR.mvc

@@ -1,19 +0,0 @@
-SimpleClassDiagrams PetriNets_Runtime{
-    Class Natural {}
-    Class Boolean {}
-    Class String {}
-
-    Class Place {
-        tokens : Natural
-        name : String
-    }
-    Class Transition {
-        executing : Boolean
-    }
-    Association P2T (Place, Transition) {
-        weight : Natural
-    }
-    Association T2P (Transition, Place) {
-        weight : Natural
-    }
-}

+ 0 - 26
integration/code/pn_runtime_model_MR.mvc

@@ -1,26 +0,0 @@
-PetriNets_Runtime pn {
-	Place p1 {
-		tokens = 1
-        name = "p1"
-	}
-	Place p2 {
-		tokens = 2
-        name = "p2"
-	}
-	Place p3 {
-		tokens = 3
-        name = "p3"
-	}
-	Transition t1 {
-		executing = False
-	}
-	P2T (p1, t1) {
-		weight = 1
-	}
-	P2T (p2, t1) {
-		weight = 1
-	}
-	T2P (t1, p3) {
-		weight = 2
-	}
-}

+ 15 - 19
integration/code/pn_runtime_to_design.mvc

@@ -1,4 +1,6 @@
 import models/RAM_PetriNets_Design_Runtime as RAM_PN_DR
+include "primitives.alh"
+include "modelling.alh"
 
 RAM_PN_DR annotate {
     Composite schedule {
@@ -34,13 +36,13 @@ RAM_PN_DR annotate {
                 }
                 Post_PetriNets/Place cp2 {
                     label = "1"
-                    action = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Void function action(host_model : Element, name : String, mapping : Element):
-                            instantiate_attribute(host_model, name, "tokens", read_attribute(host_model, mapping["0"], "tokens"))
-                            instantiate_attribute(host_model, name, "name", read_attribute(host_model, mapping["0"], "name"))
-                            return!
+                    value_tokens = $
+                        Integer function value(host_model : Element, name : String, mapping : Element):
+                            return read_attribute(host_model, mapping["0"], "tokens")!
+                        $
+                    value_name = $
+                        String function value(host_model : Element, name : String, mapping : Element):
+                            return read_attribute(host_model, mapping["0"], "name")!
                         $
                 }
                 Post_R2D_PlaceLink (cp1, cp2){
@@ -96,12 +98,9 @@ RAM_PN_DR annotate {
                 }
                 Post_PetriNets/P2T rhs_cp2t_p2t2(rhs_cp2t_p2, rhs_cp2t_t2) {
                     label = "7"
-                    action = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Void function action(host_model : Element, name : String, mapping : Element):
-                            instantiate_attribute(host_model, name, "weight", read_attribute(host_model, mapping["2"], "weight"))
-                            return!
+                    value_weight = $
+                        Integer function value(host_model : Element, name : String, mapping : Element):
+                            return read_attribute(host_model, mapping["2"], "weight")!
                         $
                 }
             }
@@ -154,12 +153,9 @@ RAM_PN_DR annotate {
                 }
                 Post_PetriNets/T2P (rhs_ct2p_t2, rhs_ct2p_p2) {
                     label = "7"
-                    action = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Void function action(host_model : Element, name : String, mapping : Element):
-                            instantiate_attribute(host_model, name, "weight", read_attribute(host_model, mapping["2"], "weight"))
-                            return!
+                    value_weight = $
+                        Integer function value(host_model : Element, name : String, mapping : Element):
+                            return read_attribute(host_model, mapping["2"], "weight")!
                         $
                 }
             }

+ 23 - 62
integration/code/pn_simulate.mvc

@@ -1,4 +1,6 @@
 import models/RAM_PetriNets_Runtime_Runtime as RAM_PN_R
+include "primitives.alh"
+include "modelling.alh"
 
 RAM_PN_R s {
     Composite schedule {
@@ -21,8 +23,6 @@ RAM_PN_R s {
 					label = "11"
 				}
 				constraint = $
-					include "primitives.alh"
-					include "modelling.alh"
 					Boolean function constraint(host_model : Element, mapping : Element):
 						Integer tokens
 						Integer weight
@@ -34,13 +34,9 @@ RAM_PN_R s {
             RHS {
                 Post_PetriNets_Runtime/Transition {
                     label = "1"
-                    action = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Void function action(host_model : Element, name : String, mapping : Element):
-                            unset_attribute(host_model, name, "executing")
-                            instantiate_attribute(host_model, name, "executing", True)
-                            return!
+                    value_executing = $
+                        Boolean function value(host_model : Element, name : String, mapping : Element):
+                            return True!
                         $
                 }
             }
@@ -49,12 +45,9 @@ RAM_PN_R s {
             LHS {
                 Pre_PetriNets_Runtime/Transition lhs_consume_t{
                     label = "0"
-                    constraint = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Boolean function constraint(host_model : Element, name : String):
-                            // Check if this node is executing currently
-                            return value_eq(read_attribute(host_model, name, "executing"), True)!
+                    constraint_executing = $
+                        Boolean function constraint(value : Boolean):
+                            return value!
                         $
                 }
                 Pre_PetriNets_Runtime/Place lhs_consume_p{
@@ -70,20 +63,9 @@ RAM_PN_R s {
                 }
                 Post_PetriNets_Runtime/Place rhs_consume_p {
                     label = "1"
-                    action = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Void function action(host_model : Element, name : String, mapping : Element):
-                            Integer tokens
-                            Integer weight
-                            tokens = read_attribute(host_model, name, "tokens")
-                            weight = read_attribute(host_model, mapping["2"], "weight")
-                            unset_attribute(host_model, name, "tokens")
-                            instantiate_attribute(host_model, name, "tokens", tokens - weight)
-                            log("Consume for " + cast_v2s(read_attribute(host_model, name, "name")))
-                            log("Previous: " + cast_v2s(tokens))
-                            log("Now: " + cast_v2s(tokens - weight))
-                            return!
+                    value_tokens = $
+                        Integer function value(host_model : Element, name : String, mapping : Element):
+                            return integer_subtraction(read_attribute(host_model, name, "tokens"), read_attribute(host_model, mapping["2"], "weight"))!
                         $
                 }
                 Post_PetriNets_Runtime/P2T (rhs_consume_p, rhs_consume_t){
@@ -95,12 +77,9 @@ RAM_PN_R s {
             LHS {
                 Pre_PetriNets_Runtime/Transition lhs_produce_t{
                     label = "0"
-                    constraint = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Boolean function constraint(host_model : Element, name : String):
-                            // Check if this node is executing currently
-                            return value_eq(read_attribute(host_model, name, "executing"), True)!
+                    constraint_executing = $
+                        Boolean function constraint(value : Boolean):
+                            return value!
                         $
                 }
                 Pre_PetriNets_Runtime/Place lhs_produce_p{
@@ -116,20 +95,9 @@ RAM_PN_R s {
                 }
                 Post_PetriNets_Runtime/Place rhs_produce_p{
                     label = "1"
-                    action = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Void function action(host_model : Element, name : String, mapping : Element):
-                            Integer tokens
-                            Integer weight
-                            tokens = read_attribute(host_model, name, "tokens")
-                            weight = read_attribute(host_model, mapping["2"], "weight")
-                            unset_attribute(host_model, name, "tokens")
-                            instantiate_attribute(host_model, name, "tokens", tokens + weight)
-                            log("Produce for " + cast_v2s(read_attribute(host_model, name, "name")))
-                            log("Previous: " + cast_v2s(tokens))
-                            log("Now: " + cast_v2s(tokens + weight))
-                            return!
+                    value_tokens = $
+                        Integer function value(host_model : Element, name : String, mapping : Element):
+                            return integer_addition(read_attribute(host_model, name, "tokens"), read_attribute(host_model, mapping["2"], "weight"))!
                         $
                 }
                 Post_PetriNets_Runtime/T2P (rhs_produce_t, rhs_produce_p){
@@ -141,25 +109,18 @@ RAM_PN_R s {
             LHS {
                 Pre_PetriNets_Runtime/Transition {
                     label = "0"
-                    constraint = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Boolean function constraint(host_model : Element, name : String):
-                            // Check if this node is executing currently
-                            return value_eq(read_attribute(host_model, name, "executing"), True)!
+                    constraint_executing = $
+                        Boolean function constraint(value : Boolean):
+                            return value!
                         $
                 }
             }
             RHS {
                 Post_PetriNets_Runtime/Transition {
                     label = "0"
-                    action = $
-                        include "primitives.alh"
-                        include "modelling.alh"
-                        Void function action(host_model : Element, name : String, mapping : Element):
-                            unset_attribute(host_model, name, "executing")
-                            instantiate_attribute(host_model, name, "executing", False)
-                            return!
+                    value_executing = $
+                        Boolean function value(host_model : Element, name : String, mapping : Element):
+                            return False!
                         $
                 }
             }

+ 5 - 17
integration/code/ramified_petrinets.mvc

@@ -2,21 +2,14 @@ SCD Pre_PetriNets {
     // Add AL MM
 
     Class LHS{
-        constraint : Expression {
-            target_upper_cardinality = 1
-        }
+        constraint? : Expression
         upper_cardinality = 1
         lower_cardinality = 1
     }
     Class NAC{}
     Class Pre_Element{
-        label : String {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-        }
-        constraint : Expression {
-            target_upper_cardinality = 1
-        }
+        label : String
+        constraint? : Expression
     }
     Association (LHS, Pre_Element)
     Association (NAC, Pre_Element){
@@ -62,13 +55,8 @@ SCD Post_PetriNets{
     }
 
     Class Post_Element {
-        label : String {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-        }
-        value : Expression {
-            target_upper_cardinality = 1
-        }
+        label : String
+        value? : Expression
     }
 
     Class Post_Place{}

+ 0 - 127
integration/code/rpgame.mvc

@@ -1,127 +0,0 @@
-import models/SimpleClassDiagrams as SCD
-include "primitives.alh"
-include "object_operations.alh"
-
-SCD RPGame{
-    Class Tile {
-        $
-        Element associations
-        Element back_associations
-        Element association
-        String destination
-        associations = allOutgoingAssociationInstances(model, name, "tile_left")
-        while (0 < list_len(associations)):
-            association = set_pop(associations)
-            destination = readAssociationDestination(model, association)
-            back_associations = allOutgoingAssociationInstances(model, destination, "tile_right")
-            if (list_len(back_associations) < 1):
-                return "Left link does not have a right link back"!
-            else:
-                association = set_pop(back_associations)
-                destination = readAssociationDestination(model, association)
-                if (destination != name):
-                    return "Right link does not have a left link back to the same tile"!
-        associations = allOutgoingAssociationInstances(model, name, "tile_right")
-        while (0 < list_len(associations)):
-            association = set_pop(associations)
-            destination = readAssociationDestination(model, association)
-            back_associations = allOutgoingAssociationInstances(model, destination, "tile_left")
-            if (list_len(back_associations) < 1):
-                return "Right link does not have a left link back"!
-            else:
-                association = set_pop(back_associations)
-                destination = readAssociationDestination(model, association)
-                if (destination != name):
-                    return "Right link does not have a left link back to the same tile"!
-        associations = allOutgoingAssociationInstances(model, name, "tile_top")
-        while (0 < list_len(associations)):
-            association = set_pop(associations)
-            destination = readAssociationDestination(model, association)
-            back_associations = allOutgoingAssociationInstances(model, destination, "tile_bottom")
-            if (list_len(back_associations) < 1):
-                return "Top link does not have a bottom link back"!
-            else:
-                association = set_pop(back_associations)
-                destination = readAssociationDestination(model, association)
-                if (destination != name):
-                    return "Top link does not have a bottom link back to the same tile"!
-        associations = allOutgoingAssociationInstances(model, name, "tile_bottom")
-        while (0 < list_len(associations)):
-            association = set_pop(associations)
-            destination = readAssociationDestination(model, association)
-            back_associations = allOutgoingAssociationInstances(model, destination, "tile_top")
-            if (list_len(back_associations) < 1):
-                return "Bottom link does not have a top link back"!
-            else:
-                association = set_pop(back_associations)
-                destination = readAssociationDestination(model, association)
-                if (destination != name):
-                    return "Bottom link does not have a top link back to the same tile"!
-        return "OK"!
-        $
-    }
-    Association tile_left (Tile, Tile){
-        source_upper_cardinality = 1
-        target_upper_cardinality = 1
-    }
-    Association tile_right (Tile, Tile){
-        source_upper_cardinality = 1
-        target_upper_cardinality = 1
-    }
-    Association tile_top (Tile, Tile){
-        source_upper_cardinality = 1
-        target_upper_cardinality = 1
-    }
-    Association tile_bottom (Tile, Tile){
-        source_upper_cardinality = 1
-        target_upper_cardinality = 1
-    }
-    Class Scene {}
-    Association Scene_has_tiles (Scene, Tile){
-        source_lower_cardinality = 1
-        source_upper_cardinality = 1
-        target_lower_cardinality = 1
-    }
-    Class Item {}
-    Association Item_on_tile (Item, Tile){
-        source_upper_cardinality = 1
-        target_lower_cardinality = 1
-        target_upper_cardinality = 1
-    }
-    Class Goal : Item {}
-    Class Character {}
-    Association Character_on_tile (Character, Tile){
-        source_upper_cardinality = 1
-        target_lower_cardinality = 1
-        target_upper_cardinality = 1
-    }
-    Class Hero : Character {}
-}
-
-export RPGame to models/RPGame
-
-RPGame my_game {
-    Scene scene {}
-    Hero link {}
-    Goal goal {}
-    Tile tile_00 {}
-    Tile tile_01 {}
-    Tile tile_10 {}
-    Tile tile_11 {}
-    Scene_has_tiles (scene, tile_00) {}
-    Scene_has_tiles (scene, tile_01) {}
-    Scene_has_tiles (scene, tile_10) {}
-    Scene_has_tiles (scene, tile_11) {}
-    Character_on_tile (link, tile_00) {}
-    Item_on_tile (goal, tile_11) {}
-    tile_left (tile_01, tile_00) {}
-    tile_right (tile_00, tile_01) {}
-    tile_left (tile_11, tile_10) {}
-    tile_right (tile_10, tile_11) {}
-    tile_top (tile_10, tile_00) {}
-    tile_bottom (tile_00, tile_10) {}
-    tile_top (tile_11, tile_01) {}
-    tile_bottom (tile_01, tile_11) {}
-}
-
-export my_game to models/my_game

+ 0 - 97
integration/code/rpgame_semantics.alc

@@ -1,97 +0,0 @@
-include "primitives.alh"
-include "modelling.alh"
-include "object_operations.alh"
-include "library.alh"
-include "conformance_scd.alh"
-include "random.alh"
-
-Void function main():
-	Element model
-	String verify_result
-
-	while (True):
-		output("Which model do you want to execute with RPGame semantics?")
-		model = import_node(input())
-
-		if (element_eq(model, read_root())):
-			output("Could not find model; aborting")
-		elif (element_neq(model["metamodel"], import_node("models/RPGame"))):
-			log("Got metamodel: " + cast_e2s(model["metamodel"]))
-			log("Expected metamodel: " + cast_e2s(import_node("models/RPGame")))
-			output("Not a RPGame model; aborting")
-		else:
-			verify_result = conformance_scd(model)
-			if (verify_result == "OK"):
-				output("Model OK!")
-				execute_rpgame(model)
-			else:
-				output("Non-conforming model: " + verify_result)
-
-	return!
-
-String function getHeroTile(model : Element, hero : String):
-	return set_pop(followAssociation(model, hero, "Character_on_tile"))!
-
-String function getGoalTile(model : Element, goal : String):
-	return set_pop(followAssociation(model, goal, "Item_on_tile"))!
-
-Void function setHeroTile(model : Element, hero : String, tile : String):
-	Element assocs
-
-	assocs = allOutgoingAssociationInstances(model, hero, "Character_on_tile")
-	while (0 < list_len(assocs)):
-		model_delete_element(model, set_pop(assocs))
-
-	instantiate_link(model, "Character_on_tile", "", hero, tile)
-
-	return!
-
-Element function getConnectedTiles(model : Element, tile : String):
-	Element left
-	Element right
-	Element top
-	Element bottom
-	Element result
-
-	result = create_node()
-	left = followAssociation(model, tile, "tile_left")
-	right = followAssociation(model, tile, "tile_right")
-	top = followAssociation(model, tile, "tile_top")
-	bottom = followAssociation(model, tile, "tile_bottom")
-
-	while (dict_len(left) > 0):
-		set_add(result, set_pop(left))
-	while (dict_len(right) > 0):
-		set_add(result, set_pop(right))
-	while (dict_len(top) > 0):
-		set_add(result, set_pop(top))
-	while (dict_len(bottom) > 0):
-		set_add(result, set_pop(bottom))
-
-	return result!
-
-Void function execute_rpgame(model : Element):
-	String hero
-	String goal
-	String hero_tile
-	String goal_tile
-
-	log("Executing model!")
-
-	// Make the assumption that only a single hero and goal exist
-	hero = set_pop(allInstances(model, "Hero"))
-	goal = set_pop(allInstances(model, "Goal"))
-
-	log("Got all tiles")
-	goal_tile = getGoalTile(model, goal)
-	log("Got goal tile: " + goal_tile)
-	hero_tile = getHeroTile(model, hero)
-	log("Got hero tile: " + hero_tile)
-
-	log("Keep executing")
-	while (hero_tile != goal_tile):
-		output((("Hero: " + hero_tile) + " -- Goal: ") + goal_tile)
-		hero_tile = random_choice(getConnectedTiles(model, hero_tile))
-		setHeroTile(model, hero, hero_tile)
-	output("Hero reached goal!")
-	return!

+ 19 - 21
integration/code/several_petrinets.mvc

@@ -1,35 +1,33 @@
 import models/SimpleClassDiagrams as SCD
 include "primitives.alh"
+include "modelling.alh"
 
 SCD PetriNets{
-    Class Natural {
-        $
-            if (bool_not(is_physical_int(self))):
-                return "Natural has no integer value at " + name!
-            elif (integer_lt(self, 0)):
-                return "Natural does not have a positive or zero value at " + name!
-            else:
-                return "OK"!
-         $
+    SimpleAttribute Natural {
+        constraint =
+            $
+            String function constraint_Natural(model : Element, name : String):
+                Element self
+                self = model["model"][name]
+                if (is_physical_int(self)):
+                    if (integer_gte(self, 0)):
+                        return "OK"!
+                    else:
+                        return ("Natural does not have a positive or zero value at " + name)!
+                else:
+                    return ("Natural has no integer value at " + name)!
+            $
     }
+
     Class Place{
-        tokens : Natural {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-            }
+        tokens : Natural
     }
     Class Transition{}
     Association P2T (Place, Transition) {
-        weight : Natural {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-            }
+        weight : Natural
     }
     Association T2P (Transition, Place) {
-        weight : Natural {
-            target_lower_cardinality = 1
-            target_upper_cardinality = 1
-            }
+        weight : Natural
     }
 }
 

+ 22 - 12
integration/code/simpleclassdiagrams.mvc

@@ -1,21 +1,31 @@
 import /formalisms/SimpleClassDiagrams as SCD
 
 SCD SimpleClassDiagrams{
-    Class Any {}
-    Class Natural {}
-    Class String {}
+    SimpleAttribute Natural {}
+    SimpleAttribute String {}
+    SimpleAttribute Boolean {}
+
+    Class Element {}
     Class Class{
-        lower_cardinality : Natural
-        upper_cardinality : Natural
+        lower_cardinality? : Natural
+        upper_cardinality? : Natural
+    }
+
+    Association Association (Element, Element){
+        source_lower_cardinality? : Natural
+        source_upper_cardinality? : Natural
+        target_lower_cardinality? : Natural
+        target_upper_cardinality? : Natural
     }
-    Association Association (Class, Class){
+
+    Association Attribute (Element, AttributeValue) {
+        optional : Boolean
         name : String
-        source_lower_cardinality : Natural
-        source_upper_cardinality : Natural
-        target_lower_cardinality : Natural
-        target_upper_cardinality : Natural
     }
-    Association Inheritance (Class, Class){}
+
+    Class AttributeValue {}
+    Association Inheritance (Element, Element){}
     Inheritance assoc_inh_class (Association, Class) {}
-    Inheritance class_inh_any (Class, Any) {}
+    Inheritance class_inh_element (Class, Element) {}
+    Inheritance attributevalue_inh_element (AttributeValue, Element) {}
 }

+ 318 - 245
integration/test_constructors_models.py

@@ -2,247 +2,233 @@ import unittest
 import sys
 import os
 
-from utils import execute, kill, run_file, run_barebone
+from utils import execute, kill, run_file, run_barebone, get_constructor
 
 bottom = [
         "model",
         "instantiate_bottom", "1",
+        "add_node", "1", "Element",
         "add_node", "1", "Class",
-        "add_node", "1", "Any",
+        "add_node", "1", "Attribute",
+        "add_node", "1", "SimpleAttribute",
         "add_node", "1", "String",
-        "add_value", "1", "name", "name",
-        "add_edge", "1", "Association", "Class", "Any",
-        "add_edge", "1", "Inheritance", "Class", "Class",
-        "add_edge", "1", "Association_attribute", "Association", "String",
-        "add_edge", "1", "Association_name", "Association_attribute", "name",
-        "add_edge", "1", "assoc_inh_class", "Association", "Class",
-        "add_edge", "1", "class_inh_any", "Class", "Any",
-        "add_edge", "1", "string_inh_any", "String", "Any",
+        "add_value", "1", "name_value", "name",
+        "add_edge", "1", "Association", "Class", "Class",
+        "add_edge", "1", "Inheritance", "Element", "Element",
+        "add_edge", "1", "AttributeLink", "Element", "Attribute",
+        "add_edge", "1", "attr_name", "AttributeLink", "String",
+        "add_edge", "1", "attr_name_name", "attr_name", "name_value",
+        "add_edge", "1", "class_inh_element", "Class", "Element",
+        "add_edge", "1", "attribute_inh_element", "Attribute", "Element",
+        "add_edge", "1", "simple_inh_attribute", "SimpleAttribute", "Attribute",
+        "add_edge", "1", "association_inh_element", "Association", "Element",
+        "add_edge", "1", "attributelink_inh_element", "AttributeLink", "Element",
+
         "retype_model", "1", "1",
+        "retype", "1", "Element", "Class",
         "retype", "1", "Class", "Class",
-        "retype", "1", "Any", "Class",
-        "retype", "1", "String", "Class",
-        "retype", "1", "name", "String",
+        "retype", "1", "Attribute", "Class",
+        "retype", "1", "SimpleAttribute", "Class",
+        "retype", "1", "String", "SimpleAttribute",
+        "retype", "1", "name_value", "String",
         "retype", "1", "Association", "Association",
         "retype", "1", "Inheritance", "Association",
-        "retype", "1", "Association_attribute", "Association",
-        "retype", "1", "Association_name", "Association_attribute",
-        "retype", "1", "assoc_inh_class", "Inheritance",
-        "retype", "1", "class_inh_any", "Inheritance",
-        "retype", "1", "string_inh_any", "Inheritance",
-        "export_node", "1", "models/SimpleClassDiagrams",
+        "retype", "1", "AttributeLink", "Association",
+        "retype", "1", "attr_name", "AttributeLink",
+        "retype", "1", "attr_name_name", "attr_name",
+        "retype", "1", "class_inh_element", "Inheritance",
+        "retype", "1", "attribute_inh_element", "Inheritance",
+        "retype", "1", "simple_inh_attribute", "Inheritance",
+        "retype", "1", "association_inh_element", "Inheritance",
+        "retype", "1", "attributelink_inh_element", "Inheritance",
+
+        "instantiate_node", "1", "SimpleAttribute", "Location",
+        "instantiate_node", "1", "SimpleAttribute", "Natural",
+        "instantiate_node", "1", "SimpleAttribute", "Boolean",
+        "instantiate_link", "1", "AttributeLink", "attr_optional", "AttributeLink", "Boolean",
+        "instantiate_attribute", "1", "attr_optional", "name", "optional",
+        "instantiate_attribute", "1", "attr_optional", "optional", False,
+        "instantiate_attribute", "1", "attr_name", "optional", False,
+
+        "instantiate_node", "1", "Class", "ComplexAttribute",
+        "instantiate_link", "1", "Inheritance", "", "ComplexAttribute", "Attribute",
+
+        "model_define_attribute", "1", "Class", "lower_cardinality", True, "Natural",
+        "model_define_attribute", "1", "Class", "upper_cardinality", True, "Natural",
+        "model_define_attribute", "1", "Association", "source_lower_cardinality", True, "Natural",
+        "model_define_attribute", "1", "Association", "source_upper_cardinality", True, "Natural",
+        "model_define_attribute", "1", "Association", "target_lower_cardinality", True, "Natural",
+        "model_define_attribute", "1", "Association", "target_upper_cardinality", True, "Natural",
+        "model_define_attribute", "1", "ComplexAttribute", "type", False, "Location",
+
+        "export_node", "1", "models/SimpleClassDiagrams_new",
         "exit",
     ]
 
-action_language = [
+bottom_link_al = [
         "model",
-        "instantiate_node", "1", "Class", "Action",
-        "instantiate_node", "1", "Class", "Statement",
-        "instantiate_node", "1", "Class", "Expression",
-        "instantiate_node", "1", "Class", "funcdef",
-        "instantiate_node", "1", "Class", "param",
-        "instantiate_node", "1", "Class", "if",
-        "instantiate_node", "1", "Class", "break",
-        "instantiate_node", "1", "Class", "while",
-        "instantiate_node", "1", "Class", "continue",
-        "instantiate_node", "1", "Class", "assign",
-        "instantiate_node", "1", "Class", "return",
-        "instantiate_node", "1", "Class", "output",
-        "instantiate_node", "1", "Class", "declare",
-        "instantiate_node", "1", "Class", "global",
-        "instantiate_node", "1", "Class", "access",
-        "instantiate_node", "1", "Class", "constant",
-        "instantiate_node", "1", "Class", "input",
-        "instantiate_node", "1", "Class", "resolve",
-        "instantiate_node", "1", "Class", "call",
-        "instantiate_link", "1", "Association", "dict_link", "Action", "Any",
-        "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", "", "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",
-        "instantiate_link", "1", "Inheritance", "", "if", "Statement",
-        "instantiate_link", "1", "Inheritance", "", "break", "Statement",
-        "instantiate_link", "1", "Inheritance", "", "continue", "Statement",
-        "instantiate_link", "1", "Inheritance", "", "global", "Statement",
-        "instantiate_link", "1", "Inheritance", "", "while", "Statement",
-        "instantiate_link", "1", "Inheritance", "", "assign", "Statement",
-        "instantiate_link", "1", "Inheritance", "", "return", "Statement",
-        "instantiate_link", "1", "Inheritance", "", "call", "Statement",
-        "instantiate_link", "1", "Inheritance", "", "declare", "Statement",
-        "instantiate_link", "1", "Inheritance", "", "call", "Expression",
-        "instantiate_link", "1", "Inheritance", "", "access", "Expression",
-        "instantiate_link", "1", "Inheritance", "", "constant", "Expression",
-        "instantiate_link", "1", "Inheritance", "", "input", "Expression",
-        "instantiate_link", "1", "Association", "statement_next", "Statement", "Statement",
-        "instantiate_attribute", "1", "statement_next", "name", "next",
-        "instantiate_link", "1", "Association", "if_cond", "if", "Expression",
-        "instantiate_attribute", "1", "if_cond", "name", "cond",
-        "instantiate_link", "1", "Association", "if_then", "if", "Statement",
-        "instantiate_attribute", "1", "if_then", "name", "true",
-        "instantiate_link", "1", "Association", "if_else", "if", "Statement",
-        "instantiate_attribute", "1", "if_else", "name", "false",
-        "instantiate_link", "1", "Association", "while_cond", "while", "Expression",
-        "instantiate_attribute", "1", "while_cond", "name", "cond",
-        "instantiate_link", "1", "Association", "while_body", "while", "Statement",
-        "instantiate_attribute", "1", "while_body", "name", "body",
-        "instantiate_link", "1", "Association", "assign_var", "assign", "Any",
-        "instantiate_attribute", "1", "assign_var", "name", "var",
-        "instantiate_link", "1", "Association", "assign_value", "assign", "Expression",
-        "instantiate_attribute", "1", "assign_value", "name", "value",
-        "instantiate_link", "1", "Association", "break_while", "break", "while",
-        "instantiate_attribute", "1", "break_while", "name", "while",
-        "instantiate_link", "1", "Association", "continue_while", "continue", "while",
-        "instantiate_attribute", "1", "continue_while", "name", "while",
-        "instantiate_link", "1", "Association", "return_value", "return", "Expression",
-        "instantiate_attribute", "1", "return_value", "name", "value",
-        "instantiate_link", "1", "Association", "resolve_var", "resolve", "Any",
-        "instantiate_attribute", "1", "resolve_var", "name", "var",
-        "instantiate_link", "1", "Association", "access_var", "access", "Any",
-        "instantiate_attribute", "1", "access_var", "name", "var",
-        "instantiate_link", "1", "Association", "constant_node", "constant", "Any",
-        "instantiate_attribute", "1", "constant_node", "name", "node",
-        "instantiate_link", "1", "Association", "output_node", "output", "Expression",
-        "instantiate_attribute", "1", "output_node", "name", "node",
-        "instantiate_link", "1", "Association", "global_var", "global", "String",
-        "instantiate_attribute", "1", "global_var", "name", "var",
-        "instantiate_link", "1", "Association", "param_name", "param", "String",
-        "instantiate_attribute", "1", "param_name", "name", "name",
-        "instantiate_link", "1", "Association", "param_value", "param", "Expression",
-        "instantiate_attribute", "1", "param_value", "name", "value",
-        "instantiate_link", "1", "Association", "param_next_param", "param", "param",
-        "instantiate_attribute", "1", "param_next_param", "name", "next_param",
-        "instantiate_link", "1", "Association", "funcdef_body", "funcdef", "Statement",
-        "instantiate_attribute", "1", "funcdef_body", "name", "body",
-        "instantiate_link", "1", "Association", "call_func", "call", "Expression",
-        "instantiate_attribute", "1", "call_func", "name", "func",
-        "instantiate_link", "1", "Association", "call_params", "call", "param",
-        "instantiate_attribute", "1", "call_params", "name", "params",
-        "instantiate_link", "1", "Association", "call_last_param", "call", "param",
-        "instantiate_attribute", "1", "call_last_param", "name", "last_param",
-
-        "instantiate_link", "1", "Inheritance", "", "statement_next", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "if_cond", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "if_then", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "if_else", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "while_cond", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "while_body", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "assign_var", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "assign_value", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "break_while", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "continue_while", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "return_value", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "resolve_var", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "access_var", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "constant_node", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "output_node", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "global_var", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "param_name", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "param_value", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "param_next_param", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "funcdef_body", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "call_func", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "call_params", "dict_link",
-        "instantiate_link", "1", "Inheritance", "", "call_last_param", "dict_link",
-
-        "instantiate_link", "1", "Association", "constraint", "Class", "funcdef",
-        "instantiate_attribute", "1", "constraint", "name", "constraint",
+        "instantiate_node", "1", "ComplexAttribute", "ActionLanguage",
+        "instantiate_attribute", "1", "ActionLanguage", "type", "models/ActionLanguage",
+
+        "model_define_attribute", "1", "Element", "constraint", True, "ActionLanguage",
         "exit",
     ]
 
-bottom_attributes = [
+action_language = [
         "model",
-        "instantiate_node", "1", "Class", "Integer",
-        "instantiate_link", "1", "Inheritance", "integer_inh_any", "Integer", "Any",
-        "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",
+        "instantiate_model", "1", "2",
+        "instantiate_node", "2", "Class", "Element",
+        "instantiate_node", "2", "Class", "Action",
+        "instantiate_node", "2", "Class", "Statement",
+        "instantiate_node", "2", "Class", "Expression",
+        "instantiate_node", "2", "Class", "funcdef",
+        "instantiate_node", "2", "Class", "param",
+        "instantiate_node", "2", "Class", "if",
+        "instantiate_node", "2", "Class", "break",
+        "instantiate_node", "2", "Class", "while",
+        "instantiate_node", "2", "Class", "continue",
+        "instantiate_node", "2", "Class", "assign",
+        "instantiate_node", "2", "Class", "return",
+        "instantiate_node", "2", "Class", "output",
+        "instantiate_node", "2", "Class", "declare",
+        "instantiate_node", "2", "Class", "global",
+        "instantiate_node", "2", "Class", "access",
+        "instantiate_node", "2", "Class", "constant",
+        "instantiate_node", "2", "Class", "input",
+        "instantiate_node", "2", "Class", "resolve",
+        "instantiate_node", "2", "Class", "call",
+        "instantiate_node", "2", "Class", "String",
+        "instantiate_node", "2", "SimpleAttribute", "StringAttr",
+
+        "instantiate_node", "2", "Class", "Initial",
+        "instantiate_attribute", "2", "Initial", "lower_cardinality", 1,
+        "instantiate_attribute", "2", "Initial", "upper_cardinality", 1,
+        "instantiate_link", "2", "Association", "initial_funcdef", "Initial", "Action",
+        "instantiate_attribute", "2", "initial_funcdef", "target_lower_cardinality", 1,
+        "instantiate_attribute", "2", "initial_funcdef", "target_upper_cardinality", 1,
+
+        "instantiate_link", "2", "Inheritance", "", "Action", "Element",
+        "instantiate_link", "2", "Inheritance", "", "funcdef", "Action",
+        "instantiate_link", "2", "Inheritance", "", "param", "Action",
+        "instantiate_link", "2", "Inheritance", "", "Statement", "Action",
+        "instantiate_link", "2", "Inheritance", "", "Expression", "Action",
+        "instantiate_link", "2", "Inheritance", "", "resolve", "Statement",
+        "instantiate_link", "2", "Inheritance", "", "if", "Statement",
+        "instantiate_link", "2", "Inheritance", "", "break", "Statement",
+        "instantiate_link", "2", "Inheritance", "", "continue", "Statement",
+        "instantiate_link", "2", "Inheritance", "", "global", "Statement",
+        "instantiate_link", "2", "Inheritance", "", "while", "Statement",
+        "instantiate_link", "2", "Inheritance", "", "assign", "Statement",
+        "instantiate_link", "2", "Inheritance", "", "return", "Statement",
+        "instantiate_link", "2", "Inheritance", "", "call", "Statement",
+        "instantiate_link", "2", "Inheritance", "", "declare", "Statement",
+        "instantiate_link", "2", "Inheritance", "", "call", "Expression",
+        "instantiate_link", "2", "Inheritance", "", "access", "Expression",
+        "instantiate_link", "2", "Inheritance", "", "constant", "Expression",
+        "instantiate_link", "2", "Inheritance", "", "input", "Expression",
+        "instantiate_link", "2", "Inheritance", "", "String", "Element",
+
+        "instantiate_link", "2", "Association", "dict_link", "Action", "Element",
+        "model_define_attribute", "2", "dict_link", "name", False, "StringAttr",
+        "instantiate_attribute", "2", "dict_link", "target_upper_cardinality", 1,
+
+        "instantiate_link", "2", "Association", "Statement_next", "Statement", "Statement",
+        "instantiate_link", "2", "Association", "if_cond", "if", "Expression",
+        "instantiate_link", "2", "Association", "if_then", "if", "Statement",
+        "instantiate_link", "2", "Association", "if_else", "if", "Statement",
+        "instantiate_link", "2", "Association", "while_cond", "while", "Expression",
+        "instantiate_link", "2", "Association", "while_body", "while", "Statement",
+        "instantiate_link", "2", "Association", "assign_var", "assign", "resolve",
+        "instantiate_link", "2", "Association", "assign_value", "assign", "Expression",
+        "instantiate_link", "2", "Association", "break_while", "break", "while",
+        "instantiate_link", "2", "Association", "continue_while", "continue", "while",
+        "instantiate_link", "2", "Association", "return_value", "return", "Expression",
+        "instantiate_link", "2", "Association", "resolve_var", "resolve", "Element",
+        "instantiate_link", "2", "Association", "access_var", "access", "resolve",
+        "instantiate_link", "2", "Association", "constant_node", "constant", "Element",
+        "instantiate_link", "2", "Association", "output_node", "output", "Expression",
+        "instantiate_link", "2", "Association", "global_var", "global", "String",
+        "instantiate_link", "2", "Association", "param_name", "param", "String",
+        "instantiate_link", "2", "Association", "param_value", "param", "Expression",
+        "instantiate_link", "2", "Association", "param_next_param", "param", "param",
+        "instantiate_link", "2", "Association", "funcdef_body", "funcdef", "Statement",
+        "instantiate_link", "2", "Association", "call_func", "call", "Expression",
+        "instantiate_link", "2", "Association", "call_params", "call", "param",
+        "instantiate_link", "2", "Association", "call_last_param", "call", "param",
+
+        "instantiate_link", "2", "Inheritance", "", "Statement_next", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "if_cond", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "if_then", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "if_else", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "while_cond", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "while_body", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "assign_var", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "assign_value", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "break_while", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "continue_while", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "return_value", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "resolve_var", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "access_var", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "constant_node", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "output_node", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "global_var", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "param_name", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "param_value", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "param_next_param", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "funcdef_body", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "call_func", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "call_params", "dict_link",
+        "instantiate_link", "2", "Inheritance", "", "call_last_param", "dict_link",
+
+        "instantiate_attribute", "2", "if_else", "target_lower_cardinality", 1,
+        "instantiate_attribute", "2", "return_value", "target_lower_cardinality", 1,
+        "instantiate_attribute", "2", "param_next_param", "target_lower_cardinality", 1,
+        "instantiate_attribute", "2", "call_params", "target_lower_cardinality", 1,
+        "instantiate_attribute", "2", "call_last_param", "target_lower_cardinality", 1,
+
+        "export_node", "2", "models/ActionLanguage_new",
         "exit",
     ]
 
-def add_constraints(model):
-    return [
-            "model",
-            "add_constraint", str(model), "Integer",
-                "funcdef",
-                "constraint",
-                2, str(model*100), str(model*100+1),
-                    "if",
-                        "call",
-                            "access", "resolve", "is_physical_int",
-                            1,
-                            "call",
-                                "access", "resolve", "dict_read",
-                                2,
-                                "call",
-                                    "access", "resolve", "dict_read",
-                                    2,
-                                    "access", "resolve", str(model*100),
-                                    "const", "model",
-                                    False,
-                                "access", "resolve", str(model*100+1),
-                                False,
-                            False,
-                        "return",
-                            True,
-                                "const", "OK",
-                        True,
-                        "return",
-                            True,
-                                "const", "Integer instance is not an integer.",
-                        False,
-                    False,
-            "exit",
-        ]
+def add_constraint(model, element, code):
+    return ["model",
+            "instantiate_attribute_code", model, element, "constraint"] + \
+                get_constructor(code) + \
+            ["exit",]
 
 instantiate_scd = [
         "model",
-        "instantiate_model", "1", "2",
-        "instantiate_node", "2", "Class", "Place",
-        "instantiate_node", "2", "Class", "Transition",
-        "instantiate_node", "2", "Class", "Integer",
-        "instantiate_link", "2", "Association", "P2T", "Place", "Transition",
-        "instantiate_link", "2", "Association", "T2P", "Transition", "Place",
-        "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",
-        "export_node", "2", "models/PetriNets",
+        "instantiate_model", "1", "3",
+        "instantiate_node", "3", "Class", "Place",
+        "instantiate_node", "3", "Class", "Transition",
+        "instantiate_node", "3", "SimpleAttribute", "Natural",
+        "instantiate_link", "3", "Association", "P2T", "Place", "Transition",
+        "instantiate_link", "3", "Association", "T2P", "Transition", "Place",
+        "model_define_attribute", "3", "Place", "tokens", False, "Natural",
+        "model_define_attribute", "3", "P2T", "weight", False, "Natural",
+        "model_define_attribute", "3", "T2P", "weight", False, "Natural",
+        "export_node", "3", "models/PetriNets_new",
         "exit",
     ]
 
 instantiate_pn = [
         "model",
-        "instantiate_model", "2", "3",
-        "instantiate_node", "3", "Place", "p1",
-        "instantiate_node", "3", "Place", "p2",
-        "instantiate_node", "3", "Transition", "t1",
-        "instantiate_node", "3", "Transition", "t2",
-        "instantiate_link", "3", "P2T", "p1_t1", "p1", "t1",
-        "instantiate_link", "3", "T2P", "t1_p2", "t1", "p2",
-        "instantiate_link", "3", "P2T", "p2_t2", "p2", "t2",
-        "instantiate_link", "3", "T2P", "t2_p1", "t2", "p1",
-        "instantiate_attribute", "3", "p1_t1", "weight", 1,
-        "instantiate_attribute", "3", "t1_p2", "weight", 2,
-        "instantiate_attribute", "3", "p2_t2", "weight", 3,
-        "instantiate_attribute", "3", "t2_p1", "weight", 4,
-        "instantiate_attribute", "3", "p1", "tokens", 5,
-        "instantiate_attribute", "3", "p2", "tokens", 6,
-        "export_node", "3", "models/PN_instance",
+        "instantiate_model", "3", "4",
+        "instantiate_node", "4", "Place", "p1",
+        "instantiate_node", "4", "Place", "p2",
+        "instantiate_node", "4", "Transition", "t1",
+        "instantiate_node", "4", "Transition", "t2",
+        "instantiate_link", "4", "P2T", "p1_t1", "p1", "t1",
+        "instantiate_link", "4", "T2P", "t1_p2", "t1", "p2",
+        "instantiate_link", "4", "P2T", "p2_t2", "p2", "t2",
+        "instantiate_link", "4", "T2P", "t2_p1", "t2", "p1",
+        "instantiate_attribute", "4", "p1_t1", "weight", 1,
+        "instantiate_attribute", "4", "t1_p2", "weight", 2,
+        "instantiate_attribute", "4", "p2_t2", "weight", 3,
+        "instantiate_attribute", "4", "t2_p1", "weight", 4,
+        "instantiate_attribute", "4", "p1", "tokens", 5,
+        "instantiate_attribute", "4", "p2", "tokens", 6,
+        "export_node", "4", "models/PN_instance",
         "exit",
     ]
 
@@ -251,21 +237,19 @@ instantiate_example = [
         "instantiate_model", "1", "2",
         "instantiate_node", "2", "Class", "A",
         "instantiate_node", "2", "Class", "B",
-        "instantiate_node", "2", "Class", "C",
+        "instantiate_node", "2", "SimpleAttribute", "C",
         "instantiate_link", "2", "Inheritance", "b_inherits_a", "B", "A",
-        "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",
+        "instantiate_link", "2", "Association", "A_to_B", "A", "B",
+        "model_define_attribute", "2", "A", "tokens", False, "C",
         "export_node", "2", "models/example_MM",
         "exit",
         "model",
         "instantiate_model", "2", "3",
         "instantiate_node", "3", "A", "a",
-        "instantiate_attribute", "3", "a", "tokens", "b",
         "instantiate_node", "3", "B", "b",
-        "instantiate_node", "3", "C", "c",
-        "instantiate_attribute", "3", "c", "tokens", "b",
+        "instantiate_link", "3", "A_to_B", "a_to_b", "a", "b",
+        "instantiate_attribute", "3", "a", "tokens", 123,
+        "instantiate_attribute", "3", "b", "tokens", 234,
         "export_node", "3", "models/example_M",
         "exit",
     ]
@@ -286,24 +270,18 @@ def conformance_call(operation, model, metamodel):
 is_direct_instance = \
     conformance_call("is_direct_instance", "a", "A") + \
     conformance_call("is_direct_instance", "b", "A") + \
-    conformance_call("is_direct_instance", "c", "A") + \
     conformance_call("is_direct_instance", "a", "B") + \
     conformance_call("is_direct_instance", "b", "B") + \
-    conformance_call("is_direct_instance", "c", "B") + \
     conformance_call("is_direct_instance", "a", "C") + \
-    conformance_call("is_direct_instance", "b", "C") + \
-    conformance_call("is_direct_instance", "c", "C")
+    conformance_call("is_direct_instance", "b", "C")
 
 is_nominal_instance = \
     conformance_call("is_nominal_instance", "a", "A") + \
     conformance_call("is_nominal_instance", "b", "A") + \
-    conformance_call("is_nominal_instance", "c", "A") + \
     conformance_call("is_nominal_instance", "a", "B") + \
     conformance_call("is_nominal_instance", "b", "B") + \
-    conformance_call("is_nominal_instance", "c", "B") + \
     conformance_call("is_nominal_instance", "a", "C") + \
-    conformance_call("is_nominal_instance", "b", "C") + \
-    conformance_call("is_nominal_instance", "c", "C")
+    conformance_call("is_nominal_instance", "b", "C")
 
 def conformance_check(node):
     return [
@@ -316,45 +294,140 @@ def conformance_check(node):
                 True,
             ]
 
+code_natural = \
+    """
+        include "primitives.alh"
+        String function constraint(model : Element, name : String):
+            Element self
+            self = model["model"][name]
+            if (is_physical_int(self)):
+                if (integer_gte(self, 0)):
+                    return "OK"!
+                else:
+                    return "Natural number not larger than or equal to zero"!
+            else:
+                return "Natural number not larger than or equal to zero"!
+    """
+
+code_string = \
+    """
+        include "primitives.alh"
+        String function constraint(model : Element, name : String):
+            Element self
+            self = model["model"][name]
+            log("In constraint")
+            if (is_physical_string(self)):
+                return "OK"!
+            else:
+                return "String has non-string instance"!
+    """
+
+code_boolean = \
+    """
+        include "primitives.alh"
+        String function constraint(model : Element, name : String):
+            Element self
+            self = model["model"][name]
+            if (is_physical_boolean(self)):
+                return "OK"!
+            else:
+                return "Boolean has non-boolean instance"!
+    """
+
+code_location = \
+    """
+        include "primitives.alh"
+        include "library.alh"
+        String function constraint(model : Element, name : String):
+            Element self
+            self = model["model"][name]
+            if (is_physical_string(self)):
+                if (element_neq(import_node(self), read_root())):
+                    return "OK"!
+                else:
+                    return "Location references non-existing element!"!
+            else:
+                return "Location has non-string instance"!
+    """
+
+code_complex_attribute = \
+    """
+        include "primitives.alh"
+        include "library.alh"
+        String function constraint(model : Element, name : String):
+            Element self
+            self = model["model"][name]
+            if (is_physical_string(self)):
+                if (element_neq(import_node(self), read_root())):
+                    return "OK"!
+                else:
+                    return "Complex Attribute references non-existing element!"!
+            else:
+                return ("Complex Attribute has non-string value: " + cast_e2s(self))!
+    """
+
 class TestConstructorsModels(unittest.TestCase):
     def test_constructors_instantiate_bottom(self):
-        commands = bottom + bottom_attributes + conformance_check("models/SimpleClassDiagrams") + ["return", False]
+        commands = bottom + conformance_check("models/SimpleClassDiagrams_new") + ["return", False]
         self.assertTrue(run_barebone(commands, ["OK"], 1))
 
     def test_constructors_action_language(self):
-        commands = bottom + action_language + bottom_attributes + conformance_check("models/SimpleClassDiagrams") + ["return", False]
+        commands = bottom + action_language + bottom_link_al + \
+                    add_constraint("2", "String", code_string) + \
+                    add_constraint("2", "StringAttr", code_string) + \
+                    conformance_check("models/ActionLanguage_new") + ["return", False]
         self.assertTrue(run_barebone(commands, ["OK"], 1))
 
-    def test_constructors_constraints(self):
-        commands = bottom + action_language + bottom_attributes + add_constraints(1) + conformance_check("models/SimpleClassDiagrams") + ["return", False]
+    def test_constructors_constraints_scd(self):
+        commands = bottom + action_language + bottom_link_al + \
+                    add_constraint("2", "String", code_string) + \
+                    add_constraint("2", "StringAttr", code_string) + \
+                    add_constraint("1", "Natural", code_natural) + \
+                    add_constraint("1", "String", code_string) + \
+                    add_constraint("1", "Location", code_location) + \
+                    add_constraint("1", "Boolean", code_boolean) + \
+                    add_constraint("1", "ActionLanguage", code_complex_attribute) + \
+                    conformance_check("models/SimpleClassDiagrams_new") + ["return", False]
         self.assertTrue(run_barebone(commands, ["OK"], 1))
 
-    def test_constructors_constraints_executed(self):
-        commands = bottom + action_language + bottom_attributes + add_constraints(1) + instantiate_scd + add_constraints(2) + instantiate_pn + conformance_check("models/PN_instance") + ["return", False]
+    def test_constructors_constraints_pn(self):
+        commands = bottom + action_language + bottom_link_al + \
+                    add_constraint("2", "String", code_string) + \
+                    add_constraint("2", "StringAttr", code_string) + \
+                    add_constraint("1", "Natural", code_natural) + \
+                    add_constraint("1", "String", code_string) + \
+                    add_constraint("1", "Location", code_location) + \
+                    add_constraint("1", "Boolean", code_boolean) + \
+                    add_constraint("1", "ActionLanguage", code_complex_attribute) + \
+                    instantiate_scd + \
+                    add_constraint("3", "Natural", code_natural) + \
+                    conformance_check("models/PetriNets_new") + \
+                    instantiate_pn + \
+                    conformance_check("models/PN_instance") + ["return", False]
         self.assertTrue(run_barebone(commands, ["OK"], 1))
 
     def test_constructors_instantiate_scd(self):
-        commands = bottom + bottom_attributes + instantiate_scd + conformance_check("models/PetriNets") + ["return", False]
+        commands = bottom + instantiate_scd + conformance_check("models/PetriNets_new") + ["return", False]
         self.assertTrue(run_barebone(commands, ["OK"], 1))
 
     def test_constructors_instantiate_pn(self):
-        commands = bottom + bottom_attributes + instantiate_scd + instantiate_pn + conformance_check("models/PN_instance") + ["return", False]
+        commands = bottom + instantiate_scd + instantiate_pn + conformance_check("models/PN_instance") + ["return", False]
         self.assertTrue(run_barebone(commands, ["OK"], 1))
 
     def test_constructors_instantiate_example(self):
-        commands = bottom + bottom_attributes + instantiate_example + conformance_check("models/example_MM") + conformance_check("models/example_M") + ["return", False]
+        commands = bottom + instantiate_example + conformance_check("models/example_MM") + conformance_check("models/example_M") + ["return", False]
         self.assertTrue(run_barebone(commands, ["OK", "OK"], 1))
 
     def test_constructors_is_direct_instance(self):
-        commands = bottom + bottom_attributes + instantiate_example + is_direct_instance + ["return", False]
-        expected = [True, False, False,
-                    False, True, False,
-                    False, False, True]
+        commands = bottom + instantiate_example + is_direct_instance + ["return", False]
+        expected = [True, False,
+                    False, True,
+                    False, False]
         self.assertTrue(run_barebone(commands, expected, 1))
 
     def test_constructors_is_nominal_instance(self):
-        commands = bottom + bottom_attributes + instantiate_example + is_nominal_instance + ["return", False]
-        expected = [True, True, False,
-                    False, True, False,
-                    False, False, True]
+        commands = bottom + instantiate_example + is_nominal_instance + ["return", False]
+        expected = [True, True, 
+                    False, True,
+                    False, False]
         self.assertTrue(run_barebone(commands, expected, 1))

+ 1 - 1
integration/test_constructors_models_compiled.py

@@ -88,7 +88,7 @@ class TestConstructorsModelsCompiled(unittest.TestCase):
         self.assertTrue(run_barebone(commands, ["OK", 
                     "Natural does not have a positive or zero value at p1.tokens",
                     "Natural does not have a positive or zero value at p2t.weight",
-                    "Destination of model edge not typed by source of type: wrong_p2t",
+                    "Destination of model edge not typed by destination of type: wrong_p2t",
                     "Source of model edge not typed by source of type: wrong_t2p",
                     "Lower cardinality violation for outgoing edge of type Place_tokens at p1",
                     "Lower cardinality violation for outgoing edge of type P2T_weight at p2t",

+ 9 - 0
integration/utils.py

@@ -284,6 +284,14 @@ def run_barebone(parameters, expected, interface="0", timeout=False, wait=False,
         kill(proc)
 
 def get_constructor(code):
+    code_fragments = code.split("\n")
+    code_fragments = [i for i in code_fragments if i.strip() != ""]
+    code_fragments = [i.replace("    ", "\t") for i in code_fragments]
+    initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments])
+    code_fragments = [i[initial_tabs:] for i in code_fragments]
+    code_fragments.append("")
+    code = "\n".join(code_fragments)
+
     with open("__constraint.alc", "w") as f:
         f.write(code)
         f.flush()
@@ -299,6 +307,7 @@ def get_model_constructor(code):
     code_fragments = [i.replace("    ", "\t") for i in code_fragments]
     initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments])
     code_fragments = [i[initial_tabs:] for i in code_fragments]
+    code_fragments.append("")
     code = "\n".join(code_fragments)
 
     with open("__model.mvc", "w") as f:

+ 3 - 3
interface/HUTN/grammars/modelling.g

@@ -12,9 +12,8 @@ grammar{
     inheritance: COLON MODEL_ID (COMMA MODEL_ID)*;
 
     model_attribute : ((LCURLY MODEL_ID RCURLY)? model_element)
-                    | (MODEL_ID COLON MODEL_ID (LCURLY NEWLINE? model_attr_instance* RCURLY)? NEWLINE?)
-                    | (model_attr_instance)
-                    | (NEWLINE? DOLLAR ANYTHING_EXCEPT_DOLLAR DOLLAR NEWLINE?);
+                    | (MODEL_ID OPTIONAL? COLON MODEL_ID (LCURLY NEWLINE? model_attr_instance* RCURLY)? NEWLINE?)
+                    | (model_attr_instance);
 
     model_attr_instance: (MODEL_ID ASSIGN value NEWLINE?)
                        | (MODEL_ID ASSIGN NEWLINE? DOLLAR ANYTHING_EXCEPT_DOLLAR DOLLAR NEWLINE?);
@@ -28,6 +27,7 @@ grammar{
 
     tokens{
         IMPORT: 'import';
+        OPTIONAL: '\?';
         AS: 'as';
         MODEL_ID: '[a-zA-Z_][a-zA-Z_0-9/]*';
         MV_URL: '[a-zA-Z_0-9/]*';

+ 5 - 20
interface/HUTN/hutn_compiler/model_visitor.py

@@ -29,7 +29,7 @@ class ModelVisitor(Visitor):
             self.visit(t)
 
     def visit_include_files(self, tree):
-        self.includes.append(tree.get_children("STRVALUE")[0].get_text())
+        self.includes.append('include %s' % tree.get_children("STRVALUE")[0].get_text())
 
     def visit_import(self, tree):
         url = tree.get_children("MV_URL")[0]
@@ -87,16 +87,16 @@ class ModelVisitor(Visitor):
     def visit_model_attribute(self, tree):
         children = tree.get_children("MODEL_ID")
         is_definition = bool(tree.get_children("COLON"))
-        is_constraint = bool(tree.get_children("DOLLAR"))
         is_assign = bool(tree.get_children("model_attr_instance"))
         is_nested = bool(tree.get_children("model_element"))
 
         if is_definition:
             attr_name = children[0].get_text()
+            attr_optional = len(tree.get_children("OPTIONAL")) > 0
             attr_type = children[1].get_text()
-            self.constructors.extend(["instantiate_link", self.current_model, "Association", self.current_element[-1] + "_" + attr_name, self.current_element[-1], attr_type])
+            self.constructors.extend(["model_define_attribute", self.current_model, self.current_element[-1], attr_name, attr_optional, attr_type])
             full_attribute_name = self.current_element[-1] + "_" + attr_name
-            self.constructors.extend(["instantiate_attribute", self.current_model, full_attribute_name, "name", attr_name])
+
             if is_assign:
                 # There are also some attributes to set!
                 self.current_element.append(full_attribute_name)
@@ -107,21 +107,6 @@ class ModelVisitor(Visitor):
                 self.current_element.pop()
         elif is_assign:
             self.visit(tree.get_children("model_attr_instance")[0])
-        elif is_constraint:
-            constraint = tree.get_children("ANYTHING_EXCEPT_DOLLAR")[0].get_text()
-            whitespaces = len(constraint) - len(constraint.lstrip())
-            constraint = "\n".join(["\t" + line[whitespaces-1:].replace("    ", "\t") for line in constraint.split("\n") if len(line.strip()) != 0])
-            constraint = "".join(["include %s\n" % i for i in self.includes]) + \
-                         "String function constraint(model : Element, name : String):\n" + \
-                         "\tElement self\n" + \
-                         '\tself = model["model"][name]\n' + \
-                         constraint + "\n"
-            with open(".constraint.alc", 'w') as f:
-                f.write(constraint)
-                f.flush()
-            directory = os.path.realpath(__file__).rsplit(os.sep, 1)[0]
-            compiled = do_compile(".constraint.alc", directory + "/../grammars/actionlanguage.g", "CS")
-            self.constructors.extend(["add_constraint", self.current_model, self.current_element[-1]] + compiled)
         elif is_nested:
             if tree.get_children("MODEL_ID"):
                 contains_link = tree.get_children("MODEL_ID")[0].get_text()
@@ -137,7 +122,7 @@ class ModelVisitor(Visitor):
 	    code_fragments = [i for i in code_fragments if i.strip() != ""]
 	    code_fragments = [i.replace("    ", "\t") for i in code_fragments]
 	    initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments])
-	    code_fragments = [i[initial_tabs:] for i in code_fragments]
+	    code_fragments = self.includes + [i[initial_tabs:] for i in code_fragments]
 	    code = "\n".join(code_fragments)
             code += "\n"
 

+ 6 - 1
interface/HUTN/includes/metamodels.alh

@@ -2,4 +2,9 @@ Element function create_metamodels()
 Element function initialize_SCD(location : String)
 Element function initialize_PN(location_SCD : String, location_PN : String)
 Element function initialize_bottom(location : String)
-Void function add_AL_to_MM(model : Element)
+Element function initialize_AL(location_SCD : String, location_AL : String)
+Element function constraint_Natural(params : Element)
+Element function constraint_String(params : Element)
+Element function constraint_Location(params : Element)
+Element function constraint_Boolean(params : Element)
+Element function constraint_ActionLanguage(params : Element)

+ 2 - 2
interface/HUTN/includes/modelling.alh

@@ -19,6 +19,6 @@ Void function unset_attribute(model : Element, elem : String, name : String)
 Void function construct_model()
 Element function read_attribute(model : Element, elem : String, name : String)
 Void function model_delete_element(model : Element, name : String)
-Void function add_constraint(model : Element, name : String, constraint : Action)
-String function model_define_attribute(model : Element, elem : String, name : String, type : String)
+String function model_define_attribute(model : Element, elem : String, name : String, optional : Boolean, type : String)
 Element function construct_model_raw(metamodel : Element)
+Element function get_func_AL_model(model_location : String)

+ 1 - 1
interface/HUTN/test/modelling_language/code/my_petrinet_with_MM.mvc

@@ -1,7 +1,7 @@
 import models/SimpleClassDiagrams as SCD
 
 SCD PetriNets{
-    Class Natural {}
+    SimpleAttribute Natural {}
     Class Place{
         tokens : Natural
     }

+ 1 - 1
interface/HUTN/test/modelling_language/code/petrinets.mvc

@@ -1,7 +1,7 @@
 import models/SimpleClassDiagrams as SCD
 
 SCD PetriNets{
-    Class Natural {}
+    SimpleAttribute Natural {}
     Class Place{
         tokens : Natural
     }

+ 10 - 9
interface/HUTN/test/modelling_language/code/petrinets_constraints.mvc

@@ -2,15 +2,16 @@ import models/SimpleClassDiagrams as SCD
 include "primitives.alh"
 
 SCD PetriNets{
-    Class Natural {
-        $
-            if (bool_not(is_physical_int(self))):
-                return "Natural has no integer value"!
-            elif (integer_lt(self, 0)):
-                return "Natural does not have a positive or zero value"!
-            else:
-                return "OK"!
-         $
+    SimpleAttribute Natural {
+        constraint = $
+            String function constraint(model : Element, name : String):
+                if (bool_not(is_physical_int(model["model"][name]))):
+                    return "Natural has no integer value"!
+                elif (integer_lt(model["model"][name], 0)):
+                    return "Natural does not have a positive or zero value"!
+                else:
+                    return "OK"!
+            $
     }
     Class Place{
         tokens : Natural

+ 2 - 2
interface/HUTN/test/modelling_language/code/simpleclassdiagrams.mvc

@@ -2,8 +2,8 @@ import /formalisms/SimpleClassDiagrams as SCD
 
 SCD SimpleClassDiagrams{
     Class Any {}
-    Class Natural {}
-    Class String {}
+    SimpleAttribute Natural {}
+    SimpleAttribute String {}
     Class Class{
         lower_cardinality : Natural
         upper_cardinality : Natural

文件差異過大導致無法顯示
+ 1 - 1
interface/HUTN/test/modelling_language/expected/my_petrinet


文件差異過大導致無法顯示
+ 1 - 1
interface/HUTN/test/modelling_language/expected/my_petrinet_with_MM


文件差異過大導致無法顯示
+ 1 - 1
interface/HUTN/test/modelling_language/expected/petrinets


文件差異過大導致無法顯示
+ 1 - 1
interface/HUTN/test/modelling_language/expected/petrinets_constraints


文件差異過大導致無法顯示
+ 1 - 1
interface/HUTN/test/modelling_language/expected/simpleclassdiagrams


+ 1 - 0
scripts/run_MvC_server.py

@@ -20,6 +20,7 @@ subprocess.check_call([sys.executable, "-m", "sccd.compiler.sccdc", "-p", "threa
 # Start up the MvK as a subprocess
 try:
     obj = subprocess.Popen([sys.executable, "run_mvk_server.py", str(MVK_PORT), "--kernel=baseline-jit"], cwd="hybrid_server")
+    #obj = subprocess.Popen([sys.executable, "run_mvk_server.py", str(MVK_PORT), "--kernel=legacy-interpreter"], cwd="hybrid_server")
 
     # Compile all MvC code
     subprocess.call([sys.executable, "scripts/execute_model.py", address, SETUP_USER, "bootstrap/*.alc", "core/*.alc", "core/*.mvc"])