Browse Source

Merge branch 'master' into testing

Yentl Van Tendeloo 4 years ago
parent
commit
a91ea4c321

+ 3 - 3
bootstrap/90_core_formalism.mvc

@@ -23,11 +23,11 @@ SimpleClassDiagrams CoreFormalism {
                     return "Permissions has no string value"!
                 if (bool_not(string_len(self) == 3)):
                     return "Permissions string is not of correct length"!
-                if (bool_or(cast_s2i(string_get(self, 0)) < 0, cast_s2i(string_get(self, 0)) > 2)):
+                if (bool_or(cast_integer(string_get(self, 0)) < 0, cast_integer(string_get(self, 0)) > 2)):
                     return "Owner permission is not in range [0, 2]"!
-                if (bool_or(cast_s2i(string_get(self, 1)) < 0, cast_s2i(string_get(self, 1)) > 2)):
+                if (bool_or(cast_integer(string_get(self, 1)) < 0, cast_integer(string_get(self, 1)) > 2)):
                     return "Group permission is not in range [0, 2]"!
-                if (bool_or(cast_s2i(string_get(self, 2)) < 0, cast_s2i(string_get(self, 2)) > 2)):
+                if (bool_or(cast_integer(string_get(self, 2)) < 0, cast_integer(string_get(self, 2)) > 2)):
                     return "Other permission is not in range [0, 2]"!
                 return "OK"!
             $

+ 6 - 16
bootstrap/bootstrap.py

@@ -39,22 +39,12 @@ def bootstrap():
                     "string_len": ["Integer", "String"],
                     "string_split": ["Element", "String", "String"],
                     "value_eq":  ["Boolean", "Element", "Element"],
-                    "cast_i2f": ["Float", "Integer"],
-                    "cast_i2s": ["String", "Integer"],
-                    "cast_i2b": ["Boolean", "Integer"],
-                    "cast_f2i": ["Integer", "Float"],
-                    "cast_f2b": ["Boolean", "Float"],
-                    "cast_f2s": ["String", "Float"],
-                    "cast_s2i": ["Integer", "String"],
-                    "cast_s2f": ["Float", "String"],
-                    "cast_s2b": ["Boolean", "String"],
-                    "cast_b2i": ["Integer", "Boolean"],
-                    "cast_b2f": ["Float", "Boolean"],
-                    "cast_b2s": ["String", "Boolean"],
-                    "cast_e2s": ["String", "Element"],
-                    "cast_a2s": ["String", "Action"],
-                    "cast_v2s": ["String", "Element"],
-                    "cast_id2s": ["String", "Element"],
+                    "cast_float": ["Float", "Element"],
+                    "cast_string": ["String", "Element"],
+                    "cast_boolean": ["Boolean", "Element"],
+                    "cast_integer": ["Integer", "Element"],
+                    "cast_value": ["String", "Element"],
+                    "cast_id": ["String", "Element"],
                     "list_insert": ["Element", "Element", "Integer", "Element"],
                     "list_delete": ["Element", "Element", "Integer"],
                     "dict_add_fast": ["Element", "Element", "Element", "Element"],

+ 4 - 4
bootstrap/conformance_scd.alc

@@ -159,10 +159,10 @@ String function conformance_scd(model : Element):
 				return "Type of element not in specified metamodel: " + model_info(model, model_name)!
 
 			if (is_edge(element)):
-				src_model = reverse_m[cast_id2s(read_edge_src(element))]
-				dst_model = reverse_m[cast_id2s(read_edge_dst(element))]
-				src_metamodel = reverse_mm[cast_id2s(read_edge_src(metamodel["model"][typing[model_name]]))]
-				dst_metamodel = reverse_mm[cast_id2s(read_edge_dst(metamodel["model"][typing[model_name]]))]
+				src_model = reverse_m[cast_id(read_edge_src(element))]
+				dst_model = reverse_m[cast_id(read_edge_dst(element))]
+				src_metamodel = reverse_mm[cast_id(read_edge_src(metamodel["model"][typing[model_name]]))]
+				dst_metamodel = reverse_mm[cast_id(read_edge_dst(metamodel["model"][typing[model_name]]))]
 
 				if (bool_not(is_nominal_instance(model, src_model, src_metamodel))):
 					log("got: " + src_model)

+ 4 - 4
bootstrap/constructors.alc

@@ -36,8 +36,8 @@ Element function construct_function_list(list : Element):
 		elif (command == "mutable_funcdef"):
 			result = construct_funcdef(True, list)
 		else:
-			log("ERROR (1): did not understand command " + cast_e2s(command))
-			output("ERROR: compiled code not understood: " + cast_e2s(command))
+			log("ERROR (1): did not understand command " + cast_value(command))
+			output("ERROR: compiled code not understood: " + cast_value(command))
 			return read_root()!
 
 		continue = list_pop_final(list)
@@ -218,8 +218,8 @@ Element function construct_unknown(list : Element):
 	elif (elem == "continue"):
 		return construct_continue(list)!
 	else:
-		log("ERROR (2): did not understand command " + cast_e2s(elem))
-		output("ERROR: compiled code not understood: " + cast_e2s(elem))
+		log("ERROR (2): did not understand command " + cast_value(elem))
+		output("ERROR: compiled code not understood: " + cast_value(elem))
 		return read_root()!
 
 Action function construct_if(list : Element):

+ 12 - 12
bootstrap/core_algorithm.alc

@@ -75,8 +75,8 @@ String function get_instanceOf_link(model_id : String, metamodel_id : String):
 		log("WARNING: multiple instanceOf relations were detected for this model; picking one at random!")
 	elif (set_len(all_links) == 0):
 		log("No types found!")
-		log("Source model: " + cast_v2s(read_attribute(core, model_id, "name")))
-		log("Target meta-model: " + cast_v2s(read_attribute(core, metamodel_id, "name")))
+		log("Source model: " + cast_value(read_attribute(core, model_id, "name")))
+		log("Target meta-model: " + cast_value(read_attribute(core, metamodel_id, "name")))
 		return read_root()!
 	
 	choice = set_pop(all_links)
@@ -127,8 +127,8 @@ Element function get_full_model(model_id : String, metamodel_id : String):
 		return m!
 	else:
 		log("No type mapping could be deduced!")
-		log("Error for " + cast_v2s(read_attribute(core, model_id, "name")))
-		log(" and type " + cast_v2s(read_attribute(core, metamodel_id, "name")))
+		log("Error for " + cast_value(read_attribute(core, model_id, "name")))
+		log(" and type " + cast_value(read_attribute(core, metamodel_id, "name")))
 		return read_root()!
 
 Integer function get_relation_to_model(user_id : String, model_id : String):
@@ -384,7 +384,7 @@ String function export_typing(model : Element, name : String):
 
 	// Create type mapping model
 	String location
-	location = "type mappings/" + cast_id2s(get_type_mapping(model))
+	location = "type mappings/" + cast_id(get_type_mapping(model))
 	export_node(location, get_type_mapping(model))
 
 	String instance_of
@@ -405,7 +405,7 @@ Void function model_create(model : Element, name : String, type_id : String, kin
 	String instance_of
 
 	// Create model itself
-	location = "models/" + cast_id2s(model)
+	location = "models/" + cast_id(model)
 	export_node(location, model["model"])
 
 	model_id = instantiate_node(core, kind, "")
@@ -428,7 +428,7 @@ Void function model_overwrite(model : Element, model_id : String, metamodel_id :
 	String location
 	String instanceOf_link
 
-	location = "models/" + cast_id2s(model)
+	location = "models/" + cast_id(model)
 	export_node(location, model["model"])
 
 	// Change location in meta-data
@@ -681,8 +681,8 @@ Element function execute_operation(operation_id : String, input_models : Element
 			Element m
 			m = get_full_model(get_entry_id(input_models[set_pop(dict_keys(input_models))]), get_entry_id(input_metamodels[set_pop(dict_keys(input_metamodels))]))
 			if (element_eq(m, read_root())):
-				log("Signature mismatch in operation for tag " + cast_v2s(set_pop(dict_keys(input_models))))
-				output("Signature mismatch in operation for tag " + cast_v2s(set_pop(dict_keys(input_models))))
+				log("Signature mismatch in operation for tag " + cast_value(set_pop(dict_keys(input_models))))
+				output("Signature mismatch in operation for tag " + cast_value(set_pop(dict_keys(input_models))))
 				return read_root()!
 			merged_model = model_copy(m)
 		elif (bool_and(dict_len(input_models) == 0, dict_len(output_metamodels) == 0)):
@@ -710,7 +710,7 @@ Element function execute_operation(operation_id : String, input_models : Element
 			return read_root()!
 		result = transform(merged_model, operation)
 	elif (exact_type == "ManualOperation"):
-		output("Please perform manual operation " + cast_v2s(full_name(operation_id)))
+		output("Please perform manual operation " + cast_value(full_name(operation_id)))
 		modify(merged_model, True)
 		result = True
 	elif (exact_type == "ActionLanguage"):
@@ -1821,7 +1821,7 @@ String function cmd_permission_modify(model_name : String, permissions : String)
 				fail = True
 
 			while (i < 3):
-				permission = cast_s2i(string_get(permissions, i))
+				permission = cast_integer(string_get(permissions, i))
 				if (bool_or(permission < 0, permission > 2)):
 					fail = True
 					break!
@@ -2070,7 +2070,7 @@ String function cmd_service_register(service_name : String):
 		output("Success: " + get_taskname())
 
 		// Wait until we can stop the service
-		while (cast_v2s(input()) != "\"service_stop\""):
+		while (cast_value(input()) != "\"service_stop\""):
 			output("Service is running on this task: stop it by sending 'service_stop'")
 
 		model_delete_element(core, service)

+ 8 - 9
bootstrap/mini_modify.alc

@@ -40,7 +40,7 @@ String function pretty_print(model : Element):
 			attr_keys = dict_keys(attr_list)
 			while (set_len(attr_keys) > 0):
 				attr_key = set_pop(attr_keys)
-				result = result + "      " + attr_key + " : " + cast_v2s(attr_list[attr_key])
+				result = result + "      " + attr_key + " : " + cast_value(attr_list[attr_key])
 				result = result + "\n"
 
 			// Has attributes
@@ -49,9 +49,9 @@ String function pretty_print(model : Element):
 			while (set_len(attr_keys) > 0):
 				attr_key = set_pop(attr_keys)
 				if (element_eq(read_attribute(model, v_m, attr_key), read_root())):
-					result = result + "      " + cast_v2s(attr_key) + " : " + cast_v2s(attr_list[attr_key]) + " = (undefined)"
+					result = result + "      " + cast_string(attr_key) + " : " + cast_string(attr_list[attr_key]) + " = (undefined)"
 				else:
-					result = result + "      " + cast_v2s(attr_key) + " : " + cast_v2s(attr_list[attr_key]) + " = " + cast_v2s(read_attribute(model, v_m, attr_key))
+					result = result + "      " + cast_string(attr_key) + " : " + cast_string(attr_list[attr_key]) + " = " + cast_value(read_attribute(model, v_m, attr_key))
 				result = result + "\n"
 		else:
 			log("Skip instance: " + type)
@@ -264,7 +264,6 @@ String function cmd_attr_optional(write : Boolean, model : Element, element_name
 				if (set_in(dict_keys(attrs), attr_name)):
 					String attr_edge
 					attr_edge = reverseKeyLookup(model["model"], dict_read_edge(model["model"][element_name], attr_name))
-					log("Was optional: " + cast_v2s(read_attribute(model, attr_edge, "optional")))
 					if (optional):
 						log("Setting to optional")
 					else:
@@ -398,7 +397,7 @@ String function cmd_read(model : Element, element_name : String):
 			result = result + "Source: " + reverseKeyLookup(model["model"], read_edge_src(model["model"][element_name])) + "\n"
 			result = result + "Destination: " + reverseKeyLookup(model["model"], read_edge_dst(model["model"][element_name])) + "\n"
 		if (has_value(model["model"][element_name])):
-			result = result + "Value: " + cast_v2s(model["model"][element_name]) + "\n"
+			result = result + "Value: " + cast_value(model["model"][element_name]) + "\n"
 		return result!
 	else:
 		return "Element not found: " + element_name!
@@ -415,7 +414,7 @@ String function cmd_read_attrs(model : Element, element_name : String):
 		attr_keys = dict_keys(attr_list)
 		while (0 < set_len(attr_keys)):
 			attr_key = set_pop(attr_keys)
-			result = string_join(result, attr_key) + " : " + cast_v2s(attr_list[attr_key]) + " = " + cast_v2s(read_attribute(model, element_name, attr_key)) + "\n"
+			result = string_join(result, attr_key) + " : " + cast_value(attr_list[attr_key]) + " = " + cast_value(read_attribute(model, element_name, attr_key)) + "\n"
 		return result!
 	else:
 		return "Element not found: " + element_name!
@@ -433,9 +432,9 @@ String function cmd_read_defined_attrs(model : Element, element_name : String):
 		while (0 < set_len(attr_keys)):
 			attr_key = set_pop(attr_keys)
 			if (value_eq(read_attribute(model, reverseKeyLookup(model["model"], dict_read_edge(model["model"][element_name], attr_key)), "optional"), True)):
-				result = string_join(result, attr_key) + " ?: " + cast_v2s(attr_list[attr_key]) + "\n"
+				result = string_join(result, attr_key) + " ?: " + cast_value(attr_list[attr_key]) + "\n"
 			else:
-				result = string_join(result, attr_key) + " : " + cast_v2s(attr_list[attr_key]) + "\n"
+				result = string_join(result, attr_key) + " : " + cast_value(attr_list[attr_key]) + "\n"
 		return result!
 	else:
 		return "Element not found: " + element_name!
@@ -564,7 +563,7 @@ Element function modify(model : Element, write : Boolean):
 		elif (cmd == "undefine_attribute"):
 			output(cmd_undefine_attribute(write, model, single_input("On which element?"), single_input("Attribute name?")))
 		else:
-			output("Unknown command while modelling: " + cmd)
+			output("Unknown command while modelling: " + cast_value(cmd))
 			output("Use command 'help' to get a list of available commands")
 	return model!
 

+ 12 - 12
bootstrap/model_management.alc

@@ -45,8 +45,8 @@ Element function model_fuse(models : Element):
 			if (is_edge(model["model"][key])):
 				String src
 				String dst
-				src = string_join(model_name, reverse[cast_id2s(read_edge_src(model["model"][key]))])
-				dst = string_join(model_name, reverse[cast_id2s(read_edge_dst(model["model"][key]))])
+				src = string_join(model_name, reverse[cast_id(read_edge_src(model["model"][key]))])
+				dst = string_join(model_name, reverse[cast_id(read_edge_dst(model["model"][key]))])
 				if (bool_and(dict_in(new_model["model"], src), dict_in(new_model["model"], dst))):
 					instantiate_link(new_model, type, model_name + key, src, dst)
 				else:
@@ -84,8 +84,8 @@ Element function model_copy(src_model : Element):
 			String src
 			String dst
 
-			src = reverse[cast_id2s(read_edge_src(src_model["model"][name]))]
-			dst = reverse[cast_id2s(read_edge_dst(src_model["model"][name]))]
+			src = reverse[cast_id(read_edge_src(src_model["model"][name]))]
+			dst = reverse[cast_id(read_edge_dst(src_model["model"][name]))]
 
 			type = read_type(src_model, name)
 
@@ -150,8 +150,8 @@ Element function model_join(models : Element, metamodel : Element, tracability_m
 			new_name = retyping_key + key
 
 			if (is_edge(model["model"][key])):
-				src = cast_id2s(read_edge_src(model["model"][key]))
-				dst = cast_id2s(read_edge_dst(model["model"][key]))
+				src = cast_id(read_edge_src(model["model"][key]))
+				dst = cast_id(read_edge_dst(model["model"][key]))
 				if (bool_and(dict_in(elem_map, src), dict_in(elem_map, dst))):
 					new_name = instantiate_link(new_model, retyping_key + type, new_name, elem_map[src], elem_map[dst])
 				else:
@@ -164,7 +164,7 @@ Element function model_join(models : Element, metamodel : Element, tracability_m
 
 			if (new_name != ""):
 				// Add the new name to a map which registers the mapping to the new name
-				dict_add_fast(elem_map, cast_id2s(model["model"][key]), new_name)
+				dict_add_fast(elem_map, cast_id(model["model"][key]), new_name)
 
 			if (set_len(keys) == 0):
 				keys = second_keys
@@ -269,8 +269,8 @@ Element function model_split(merged_model : Element, models : Element, tracabili
 				// Got a tracability link!
 				// Is always an edge (for now?)
 				// Find out source and target and hope that they are already present
-				src = reverse[cast_id2s(read_edge_src(elem))]
-				dst = reverse[cast_id2s(read_edge_dst(elem))]
+				src = reverse[cast_id(read_edge_src(elem))]
+				dst = reverse[cast_id(read_edge_dst(elem))]
 
 				// All present, so create the link between them
 				src_name = list_pop_final(string_split(src, "/"))
@@ -295,8 +295,8 @@ Element function model_split(merged_model : Element, models : Element, tracabili
 
 				if (is_edge(elem)):
 					// Is an edge, so potentially queue it
-					src = reverse[cast_id2s(read_edge_src(elem))]
-					dst = reverse[cast_id2s(read_edge_dst(elem))]
+					src = reverse[cast_id(read_edge_src(elem))]
+					dst = reverse[cast_id(read_edge_dst(elem))]
 
 					if (bool_and(dict_in(mapping, src), dict_in(mapping, dst))):
 						// All present, so create the link between them
@@ -325,6 +325,6 @@ Element function model_split(merged_model : Element, models : Element, tracabili
 	// Finally, we also add tracability information as a separate model
 	if (tracability):
 		dict_add_fast(result, "__tracability", tracability_model)
-		log("Tracability model created with # links = " + cast_v2s(dict_len(tracability_model["model"])))
+		log("Tracability model created with # links = " + cast_value(dict_len(tracability_model["model"])))
 
 	return result!

+ 9 - 9
bootstrap/modelling.alc

@@ -11,7 +11,7 @@ Element global_models = ?
 
 String function instantiated_name(element : Element, original : String):
 	if (original == ""):
-		return "__" + cast_id2s(element)!
+		return "__" + cast_id(element)!
 	else:
 		return original!
 
@@ -268,7 +268,7 @@ Void function instantiate_attribute_ref(model : Element, element : String, attri
 	attr_type = find_attribute_type(model, element, attribute_name)
 
 	if (attr_type == ""):
-		log("Could not find attribute " + cast_v2s(attribute_name))
+		log("Could not find attribute " + cast_value(attribute_name))
 		return!
 		
 	instantiate_link(model, attr_type, "", element, ref)
@@ -286,7 +286,7 @@ Void function add_code_model(model : Element, export_name : String, code : Eleme
 Void function instantiate_attribute_code(model : Element, element : String, attribute_name : String, code : Element):
 	// First create a new model for the AL part
 	String location
-	location = "code/" + cast_id2s(code)
+	location = "code/" + cast_id(code)
 
 	add_code_model(import_node("models/ActionLanguage"), location, code)
 
@@ -304,7 +304,7 @@ Void function instantiate_existing_attribute(model : Element, element : String,
 	attr_type = find_attribute_type(model, element, attribute_name)
 
 	if (attr_type == ""):
-		log("Could not find attribute " + cast_v2s(attribute_name))
+		log("Could not find attribute " + cast_value(attribute_name))
 		return!
 		
 	// Make a copy of the value, as it is likely that this value is reused later on
@@ -391,7 +391,7 @@ String function model_define_attribute(model : Element, elem : String, name : St
 	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])
+		edge_name = edge_name + cast_id(model["model"][elem])
 		log("Name clash detected for attribute: try new name: " + edge_name)
 
 	edge_name = instantiate_link(model, "AttributeLink", edge_name, elem, type)
@@ -407,7 +407,7 @@ String function model_define_attribute_ID(model : Element, elem : String, name :
 	edge_name = ID
 	while (dict_in(model["model"], edge_name)):
 		// Already exists, so make random name
-		edge_name = edge_name + cast_id2s(model["model"][elem])
+		edge_name = edge_name + cast_id(model["model"][elem])
 		log("Name clash detected for attribute: try new name: " + edge_name)
 
 	edge_name = instantiate_link(model, "AttributeLink", edge_name, elem, type)
@@ -481,7 +481,7 @@ Void function add_AL_links(model : Element, list : Element, element : Element, t
 	// The name node
 	String link_name
 	link = read_edge_dst(link)
-	link_name = "__" + cast_id2s(link)
+	link_name = "__" + cast_id(link)
 
 	if (bool_not(dict_in(model["model"], link_name))):
 		reuse_element(model, "StringAttr", link_name, link)
@@ -507,12 +507,12 @@ String function add_AL(model : Element, element : Element):
 		elem = list_read(work_node, 0)
 		type = list_read(work_node, 1)
 
-		elem_name = "__" + cast_id2s(elem)
+		elem_name = "__" + cast_id(elem)
 		if (bool_not(set_in(model["model"], elem_name))):
 			// Determine the type if we don't know it
 			if (type == ""):
 				if (is_physical_action(elem)):
-					type = cast_a2s(elem)
+					type = cast_value(elem)
 				else:
 					type = "Element"
 

+ 2 - 2
bootstrap/object_operations.alc

@@ -186,9 +186,9 @@ String function print_dict(dict : Element):
 	result = ""
 	while (0 < list_len(keys)):
 		key = set_pop(keys)
-		result = result + cast_v2s(key)
+		result = result + cast_value(key)
 		result = result + ": "
-		result = result + cast_v2s(dict[key])
+		result = result + cast_value(dict[key])
 		result = result + "\n"
 	return result!
 

+ 6 - 16
bootstrap/primitives.alc

@@ -14,22 +14,12 @@ Element function read_edge_src(a: Element) = ?primitives/read_edge_src
 Element function read_edge_dst(a: Element) = ?primitives/read_edge_dst
 Boolean function delete_element(a: Element) = ?primitives/delete_element
 Boolean function element_eq(a: Element, b: Element) = ?primitives/element_eq
-Float function cast_i2f(a: Integer) = ?primitives/cast_i2f
-String function cast_i2s(a: Integer) = ?primitives/cast_i2s
-Boolean function cast_i2b(a: Integer) = ?primitives/cast_i2b
-Integer function cast_f2i(a: Float) = ?primitives/cast_f2i
-Boolean function cast_f2b(a: Float) = ?primitives/cast_f2b
-String function cast_f2s(a: Float) = ?primitives/cast_f2s
-Integer function cast_s2i(a: String) = ?primitives/cast_s2i
-Float function cast_s2f(a: String) = ?primitives/cast_s2f
-Boolean function cast_s2b(a: String) = ?primitives/cast_s2b
-Integer function cast_b2i(a: Boolean) = ?primitives/cast_b2i
-Float function cast_b2f(a: Boolean) = ?primitives/cast_b2f
-String function cast_b2s(a: Boolean) = ?primitives/cast_b2s
-String function cast_e2s(a: Element) = ?primitives/cast_e2s
-String function cast_a2s(a: Action) = ?primitives/cast_a2s
-String function cast_v2s(a: Element) = ?primitives/cast_v2s
-String function cast_id2s(a: Element) = ?primitives/cast_id2s
+Float function cast_float(a: Element) = ?primitives/cast_float
+String function cast_string(a: Element) = ?primitives/cast_string
+Boolean function cast_boolean(a: Element) = ?primitives/cast_boolean
+Integer function cast_integer(a: Element) = ?primitives/cast_integer
+String function cast_value(a: Element) = ?primitives/cast_value
+String function cast_id(a: Element) = ?primitives/cast_id
 Element function dict_add_fast(a: Element, b: Element, c: Element) = ?primitives/dict_add_fast
 Element function dict_delete(a: Element, b: Element) = ?primitives/dict_delete
 Element function dict_delete_node(a: Element, b: Element) = ?primitives/dict_delete_node

+ 1 - 1
bootstrap/random.alc

@@ -23,7 +23,7 @@ Integer function random_interval(a : Integer, b : Integer):
 	if (a == b):
 		return a!
 	else:
-		return cast_f2i(random() * (b - a + 1) + a)!
+		return cast_integer(random() * (b - a + 1) + a)!
 
 Element function random_choice(list : Element):
 	if (list_len(list) == 0):

+ 7 - 7
bootstrap/semi_primitives.alc

@@ -22,7 +22,7 @@ Boolean function float_gt(a : Element, b : Element):
 	return bool_or(float_lt(a, b), value_eq(a, b))!
 
 Element function dict_add(a : Element, b : Element, c : Element):
-	log("Doing dict_add for " + cast_v2s(b))
+	log("Doing dict_add for " + cast_value(b))
 	create_edge(create_edge(a, c), b)
 	return a!
 
@@ -70,7 +70,7 @@ Element function set_pop(a : Element):
 		edge = read_out(a, 0)
 		result = read_edge_dst(read_out(edge, 0))
 		delete_element(edge)
-		log("Value: " + cast_v2s(result))
+		log("Value: " + cast_value(result))
 		return result!
 	else:
 		log("Set pop on empty set!")
@@ -201,7 +201,7 @@ String function set_to_string(s : Element):
 	result = "{"
 	s = set_copy(s)
 	while (set_len(s) > 0):
-		result = (result + cast_v2s(set_pop(s))) + ", "
+		result = (result + cast_value(set_pop(s))) + ", "
 	
 	result = result + "}"
 
@@ -214,7 +214,7 @@ String function list_to_string(s : Element):
 	result = "["
 	i = 0
 	while (i < list_len(s)):
-		result = result + cast_v2s(list_read(s, i))
+		result = result + cast_value(list_read(s, i))
 		result = result + ", "
 		i = i + 1
 	
@@ -242,9 +242,9 @@ String function dict_to_string(d : Element):
 	while (set_len(keys) > 0):
 		key = set_pop(keys)
 
-		result = result + cast_v2s(key)
+		result = result + cast_value(key)
 		result = result + ": "
-		result = result + cast_v2s(dict_read_node(d, key))
+		result = result + cast_value(dict_read_node(d, key))
 		if (set_len(keys) > 0):
 			result = result + ", "
 	
@@ -375,7 +375,7 @@ Element function make_reverse_dictionary(dict : Element):
 	keys = dict_keys(dict)
 	while (set_len(keys) > 0):
 		key = set_pop(keys)
-		value = cast_id2s(dict[key])
+		value = cast_id(dict[key])
 		if (dict_in(reverse, value)):
 			dict_delete(reverse, value)
 		dict_add(reverse, value, key)

+ 1 - 1
bootstrap/services.alc

@@ -16,7 +16,7 @@ String function comm_newPort():
 	String attempt
 	attempt = "__hierarchy"
 	while (dict_in(root, attempt)):
-		attempt = "__" + get_taskname() + "_" + cast_v2s(services)
+		attempt = "__" + get_taskname() + "_" + cast_value(services)
 		services = services + 1
 
 	// Create queues

+ 0 - 1
bootstrap/tracability.mvc

@@ -1,7 +1,6 @@
 import models/SimpleClassDiagrams as SimpleClassDiagrams
 
 include "primitives.alh"
-include "object_operations.alh"
 
 SimpleClassDiagrams Tracability {
     SimpleAttribute String {

+ 11 - 11
bootstrap/transform.alc

@@ -59,14 +59,14 @@ Element function make_matching_schedule(schedule_model : Element, LHS : String,
 					// If it is an edge, we should also add the target and source
 					if (is_edge(schedule_model["model"][next])):
 						// Add the target/source to the schedule
-						set_add(workset, reverse[cast_id2s(read_edge_src(schedule_model["model"][next]))])
-						set_add(workset, reverse[cast_id2s(read_edge_dst(schedule_model["model"][next]))])
+						set_add(workset, reverse[cast_id(read_edge_src(schedule_model["model"][next]))])
+						set_add(workset, reverse[cast_id(read_edge_dst(schedule_model["model"][next]))])
 
 					// Also add all outgoing links
 					counter = read_nr_out(schedule_model["model"][next])
 					while (counter > 0):
 						counter = counter - 1
-						elem_id = cast_id2s(read_out(schedule_model["model"][next], counter))
+						elem_id = cast_id(read_out(schedule_model["model"][next], counter))
 						if (dict_in(reverse, elem_id)):
 							set_add(workset, reverse[elem_id])
 
@@ -74,7 +74,7 @@ Element function make_matching_schedule(schedule_model : Element, LHS : String,
 					counter = read_nr_in(schedule_model["model"][next])
 					while (counter > 0):
 						counter = counter - 1
-						elem_id = cast_id2s(read_in(schedule_model["model"][next], counter))
+						elem_id = cast_id(read_in(schedule_model["model"][next], counter))
 						if (dict_in(reverse, elem_id)):
 							set_add(workset, reverse[elem_id])
 
@@ -299,7 +299,7 @@ Element function match(host_model : Element, schedule_model : Element, LHS : Str
 	set_add_node(mappings, initial_mapping)
 	while (list_len(schedule) > 0):
 		current_element = list_pop(schedule, list_len(schedule) - 1)
-		//log("Binding element with label " + cast_v2s(read_attribute(schedule_model, current_element, "label")))
+		//log("Binding element with label " + cast_value(read_attribute(schedule_model, current_element, "label")))
 		new_mappings = dict_create()
 
 		while (set_len(mappings) > 0):
@@ -313,7 +313,7 @@ Element function match(host_model : Element, schedule_model : Element, LHS : Str
 				set_add_node(new_mappings, new_map)
 
 		mappings = new_mappings
-		//log("Remaining options: " + cast_v2s(set_len(mappings)))
+		//log("Remaining options: " + cast_value(set_len(mappings)))
 
 		if (set_len(mappings) == 0):
 			// Stop because we have no more options remaining!
@@ -391,8 +391,8 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 		label = list_pop(labels_to_add, list_len(labels_to_add) - 1)
 		if (is_edge(schedule_model["model"][RHS_map[label]])):
 			// Edge
-			src = read_attribute(schedule_model, reverse[cast_id2s(read_edge_src(schedule_model["model"][RHS_map[label]]))], "label")
-			dst = read_attribute(schedule_model, reverse[cast_id2s(read_edge_dst(schedule_model["model"][RHS_map[label]]))], "label")
+			src = read_attribute(schedule_model, reverse[cast_id(read_edge_src(schedule_model["model"][RHS_map[label]]))], "label")
+			dst = read_attribute(schedule_model, reverse[cast_id(read_edge_dst(schedule_model["model"][RHS_map[label]]))], "label")
 
 			// First check whether both source and destination are already created
 			if (bool_and(dict_in(new_mapping, src), dict_in(new_mapping, dst))):
@@ -519,9 +519,9 @@ Boolean function transform_composite(host_model : Element, schedule_model : Elem
 			result_set = allAssociationDestinations(schedule_model, current, "OnFailure")
 
 		if (set_len(result_set) == 0):
-			log("ERROR: no next rule found for execution result " + cast_b2s(result))
+			log("ERROR: no next rule found for execution result " + cast_string(result))
 		elif (set_len(result_set) > 1):
-			log("WARNING: multiple next rules found for execution result " + cast_b2s(result))
+			log("WARNING: multiple next rules found for execution result " + cast_string(result))
 			log("Picking one at random...")
 		current = set_pop(result_set)
 
@@ -563,7 +563,7 @@ Boolean function transform_forall(host_model : Element, schedule_model : Element
 	else:
 		result = False
 
-	//log("Matches in forall: " + cast_v2s(set_len(mappings)))
+	//log("Matches in forall: " + cast_string(set_len(mappings)))
 	while (set_len(mappings) > 0):
 		mapping = set_pop(mappings)
 		RHS = set_pop(allAssociationDestinations(schedule_model, current, "RHSLink"))

+ 7 - 7
bootstrap/typing.alc

@@ -20,10 +20,10 @@ Element function get_type_mapping(model : Element):
 		mm = model["metamodel"]["model"][model["type_mapping"][key]]
 		edge = create_edge(m, mm)
 
-		dict_add_fast(tm_model, cast_id2s(m), m)
-		if (bool_not(dict_in(tm_model, cast_id2s(mm)))):
-			dict_add_fast(tm_model, cast_id2s(mm), mm)
-		dict_add_fast(tm_model, cast_id2s(edge), edge)
+		dict_add_fast(tm_model, cast_id(m), m)
+		if (bool_not(dict_in(tm_model, cast_id(mm)))):
+			dict_add_fast(tm_model, cast_id(mm), mm)
+		dict_add_fast(tm_model, cast_id(edge), edge)
 
 	return tm_model!
 
@@ -43,11 +43,11 @@ Void function set_type_mapping(model : Element, type_mapping_model : Element):
 	while (set_len(keys) > 0):
 		key = set_pop(keys)
 		if (is_edge(type_mapping_model[key])):
-			if (bool_not(bool_or(dict_in(rev_model, cast_id2s(type_mapping_model[key])), dict_in(rev_metamodel, cast_id2s(type_mapping_model[key]))))):
+			if (bool_not(bool_or(dict_in(rev_model, cast_id(type_mapping_model[key])), dict_in(rev_metamodel, cast_id(type_mapping_model[key]))))):
 				// Element is in neither model or metamodel
 				// Must be a typing link!
 				// So add it
-				dict_add_fast(type_mapping, rev_model[cast_id2s(read_edge_src(type_mapping_model[key]))], rev_metamodel[cast_id2s(read_edge_dst(type_mapping_model[key]))])
+				dict_add_fast(type_mapping, rev_model[cast_id(read_edge_src(type_mapping_model[key]))], rev_metamodel[cast_id(read_edge_dst(type_mapping_model[key]))])
 
 	dict_overwrite(model, "type_mapping", type_mapping)
 	return!
@@ -92,7 +92,7 @@ Void function remove_type(model : Element, name : String):
 	dict_delete(model["type_mapping"], name)
 	
 	String elem
-	elem = cast_id2s(model["model"][name])
+	elem = cast_id(model["model"][name])
 	if (dict_in(model["type_mapping"], elem)):
 		dict_delete(model["type_mapping"], elem)
 

+ 1 - 1
bootstrap/utils.alc

@@ -48,7 +48,7 @@ String function JSON_print(model : Element):
 						else:
 							result = result + ", \"" + attr_key + "\": false"
 					else:
-						result = result + ", \"" + attr_key + "\": " + cast_v2s(attr_value)
+						result = result + ", \"" + attr_key + "\": " + cast_value(attr_value)
 
 			result = result + "}"
 	result = result + "]"

+ 1 - 1
integration/code/pn_print.mvc

@@ -14,7 +14,7 @@ Composite schedule {
                 label = "0"
                 action = $
                     Void function action(model : Element, name : String, mapping : Element):
-                        output((cast_v2s(read_attribute(model, name, "name")) + " --> ") + cast_v2s(read_attribute(model, name, "tokens")))
+                        output((cast_value(read_attribute(model, name, "name")) + " --> ") + cast_value(read_attribute(model, name, "tokens")))
                         return!
                     $
             }

+ 6 - 6
integration/code/reachability.alc

@@ -77,8 +77,8 @@ Boolean function reachability_graph(model : Element):
 	set_add(workset, state_id)
 
 	// And add in the model itself
-	state = instantiate_node(model, "ReachabilityGraph/InitialState", cast_i2s(state_id))
-	instantiate_attribute(model, state, "name", cast_i2s(state_id))
+	state = instantiate_node(model, "ReachabilityGraph/InitialState", cast_string(state_id))
+	instantiate_attribute(model, state, "name", cast_string(state_id))
 	instantiate_attribute(model, state, "error", False)
 	keys = dict_keys(dict_repr)
 	while (read_nr_out(keys) > 0):
@@ -148,8 +148,8 @@ Boolean function reachability_graph(model : Element):
 					set_add(workset, target_id)
 
 					// And add in the model itself
-					state = instantiate_node(model, "ReachabilityGraph/State", cast_i2s(target_id))
-					instantiate_attribute(model, state, "name", cast_i2s(target_id))
+					state = instantiate_node(model, "ReachabilityGraph/State", cast_string(target_id))
+					instantiate_attribute(model, state, "name", cast_string(target_id))
 					instantiate_attribute(model, state, "error", False)
 
 					keys = dict_keys(new_dict_repr)
@@ -174,8 +174,8 @@ Boolean function reachability_graph(model : Element):
 				dict_add_fast(mappings[state_id], transition, target_id)
 
 				// And also store it in the model itself
-				new_transition = instantiate_link(model, "ReachabilityGraph/Transition", "", cast_i2s(state_id), cast_i2s(target_id))
+				new_transition = instantiate_link(model, "ReachabilityGraph/Transition", "", cast_string(state_id), cast_string(target_id))
 				instantiate_attribute(model, new_transition, "name", read_attribute(model, transition, "name"))
 
-	log("# reachable states: " + cast_v2s(next_id))
+	log("# reachable states: " + cast_value(next_id))
 	return True!

+ 4 - 4
integration/code/reachability_subfunction.alc

@@ -77,7 +77,7 @@ Boolean function main(model : Element):
 	set_add(workset, state_id)
 
 	// And add in the model itself
-	state = create_state(model, cast_i2s(state_id), dict_repr, cache, True)
+	state = create_state(model, cast_string(state_id), dict_repr, cache, True)
 
 	while (read_nr_out(workset) > 0):
 		state_id = set_pop(workset)
@@ -139,16 +139,16 @@ Boolean function main(model : Element):
 					set_add(workset, target_id)
 
 					// And add in the model itself
-					create_state(model, cast_i2s(target_id), new_dict_repr, cache, False)
+					create_state(model, cast_string(target_id), new_dict_repr, cache, False)
 
 				// Anyway, we have found a transition, which we should store
 				dict_add_fast(mappings[state_id], transition, target_id)
 
 				// And also store it in the model itself
-				new_transition = instantiate_link(model, "ReachabilityGraph/Transition", "", cast_i2s(state_id), cast_i2s(target_id))
+				new_transition = instantiate_link(model, "ReachabilityGraph/Transition", "", cast_string(state_id), cast_string(target_id))
 				instantiate_attribute(model, new_transition, "name", read_attribute(model, transition, "name"))
 
-	log("# reachable states: " + cast_v2s(next_id))
+	log("# reachable states: " + cast_string(next_id))
 	return True!
 
 String function create_state(model : Element, name : String, dict_repr : Element, cache : Element, initial : Boolean):

+ 4 - 4
integration/code/reachabilitygraph_print.mvc

@@ -24,8 +24,8 @@ Composite schedule {
                         while (set_len(all_values) > 0):
                             place = set_pop(all_values)
                             dict_add(dict_values, read_attribute(model, place, "name"), read_attribute(model, place, "tokens"))
-                        log((cast_v2s(read_attribute(model, name, "name")) + ": ") + dict_to_string(dict_values))
-                        output((cast_v2s(read_attribute(model, name, "name")) + ": ") + dict_to_string(dict_values))
+                        log((cast_value(read_attribute(model, name, "name")) + ": ") + dict_to_string(dict_values))
+                        output((cast_value(read_attribute(model, name, "name")) + ": ") + dict_to_string(dict_values))
                         return!
                     $
             }
@@ -55,8 +55,8 @@ Composite schedule {
                 label = "2"
                 action = $
                     Void function action(model : Element, name : String, mapping : Element):
-                        log((((cast_v2s(read_attribute(model, mapping["0"], "name")) + " --[") + cast_v2s(read_attribute(model, name, "name"))) + "]--> ") + cast_v2s(read_attribute(model, mapping["1"], "name")))
-                        output((((cast_v2s(read_attribute(model, mapping["0"], "name")) + " --[") + cast_v2s(read_attribute(model, name, "name"))) + "]--> ") + cast_v2s(read_attribute(model, mapping["1"], "name")))
+                        log((((cast_value(read_attribute(model, mapping["0"], "name")) + " --[") + cast_value(read_attribute(model, name, "name"))) + "]--> ") + cast_value(read_attribute(model, mapping["1"], "name")))
+                        output((((cast_value(read_attribute(model, mapping["0"], "name")) + " --[") + cast_value(read_attribute(model, name, "name"))) + "]--> ") + cast_value(read_attribute(model, mapping["1"], "name")))
                         return!
                     $
             }

+ 1 - 2
interface/HUTN/hutn_compiler/semantics_visitor.py

@@ -242,9 +242,8 @@ class SemanticsVisitor(Visitor):
 
     @staticmethod
     def cast_name(from_type, to_type):
-        from_t = str(from_type)[0].lower()
         to_t = str(to_type)[0].lower()
-        cast_name = "cast_{}2{}".format(from_t, to_t)
+        cast_name = "cast_" + {"f": "float", "i": "integer", "b": "boolean", "s": "string"}[to_t]
         return cast_name
 
     def raise_implicit_cast_error(self, from_type, to_type, tree):

+ 6 - 16
interface/HUTN/includes/primitives.alh

@@ -16,22 +16,12 @@ Element function read_edge_dst(a: Element)
 Boolean function delete_element(a: Element) 
 Boolean function element_eq(a: Element, b: Element) 
 Boolean function element_neq(a: Element, b: Element) 
-Float function cast_i2f(a: Integer)
-String function cast_i2s(a: Integer) 
-Boolean function cast_i2b(a: Integer) 
-Integer function cast_f2i(a: Float) 
-Boolean function cast_f2b(a: Float) 
-String function cast_f2s(a: Float) 
-Integer function cast_s2i(a: String) 
-Float function cast_s2f(a: String) 
-Boolean function cast_s2b(a: String) 
-Integer function cast_b2i(a: Boolean) 
-Float function cast_b2f(a: Boolean) 
-String function cast_b2s(a: Boolean) 
-String function cast_e2s(a: Element) 
-String function cast_a2s(a: Action) 
-String function cast_v2s(a: Element) 
-String function cast_id2s(a: Element) 
+Float function cast_float(a: Element)
+String function cast_string(a: Element) 
+Boolean function cast_boolean(a: Element) 
+Integer function cast_integer(a: Element) 
+String function cast_id(a: Element) 
+String function cast_value(a: Element) 
 Element function dict_add(a: Element, b: Element, c: Element)
 Element function dict_add_fast(a: Element, b: Element, c: Element)
 Element function dict_delete(a: Element, b: Element)

+ 4 - 12
kernel/modelverse_jit/intrinsics.py

@@ -37,18 +37,10 @@ UNARY_INTRINSICS = {
 }
 
 CAST_INTRINSICS = {
-    'cast_i2f' : float,
-    'cast_i2s' : str,
-    'cast_i2b' : bool,
-    'cast_f2i' : int,
-    'cast_f2s' : str,
-    'cast_f2b' : bool,
-    'cast_s2i' : int,
-    'cast_s2f' : float,
-    'cast_s2b' : bool,
-    'cast_b2i' : int,
-    'cast_b2f' : float,
-    'cast_b2s' : str
+    'cast_float' : float,
+    'cast_string' : str,
+    'cast_boolean' : bool,
+    'cast_integer' : int,
 }
 
 def create_get_length(expression):

+ 10 - 57
kernel/modelverse_kernel/primitives.py

@@ -138,77 +138,30 @@ def element_eq(a, b, **remainder):
     result, = yield [("CNV", [a == b])]
     raise PrimitiveFinished(result)
 
-def cast_a2s(a, **remainder):
+def cast_string(a, **remainder):
     a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [str(a_value["value"])])]
-    raise PrimitiveFinished(result)
-
-def cast_i2f(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [float(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_i2s(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [str(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_i2b(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [bool(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_f2i(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [int(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_f2s(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [str(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_f2b(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [bool(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_s2i(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [int(a_value)])]
+    if isinstance(a_value, dict):
+        result, = yield [("CNV", [str(a_value["value"])])]
+    else:
+        result, = yield [("CNV", [str(a_value)])]
     raise PrimitiveFinished(result)
 
-def cast_s2f(a, **remainder):
+def cast_float(a, **remainder):
     a_value, = yield [("RV", [a])]
     result, = yield [("CNV", [float(a_value)])]
     raise PrimitiveFinished(result)
 
-def cast_s2b(a, **remainder):
+def cast_boolean(a, **remainder):
     a_value, = yield [("RV", [a])]
     result, = yield [("CNV", [bool(a_value)])]
     raise PrimitiveFinished(result)
 
-def cast_b2i(a, **remainder):
+def cast_integer(a, **remainder):
     a_value, = yield [("RV", [a])]
     result, = yield [("CNV", [int(a_value)])]
     raise PrimitiveFinished(result)
 
-def cast_b2f(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [float(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_b2s(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [str(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_e2s(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", ["{ID: %s, value: %s}" % (a, a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_v2s(a, **remainder):
+def cast_value(a, **remainder):
     a_value, = yield [("RV", [a])]
     if isinstance(a_value, dict):
         # Action or type
@@ -218,7 +171,7 @@ def cast_v2s(a, **remainder):
     result, = yield [("CNV", [value])]
     raise PrimitiveFinished(result)
 
-def cast_id2s(a, **remainder):
+def cast_id(a, **remainder):
     result, = yield [("CNV", ["%s" % (a)])]
     raise PrimitiveFinished(result)
 

+ 56 - 67
kernel/test/primitives/test_cast.py

@@ -25,106 +25,95 @@ class TestCast(unittest.TestCase):
         execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
         self.primitives = read_primitive_interfaces(self.root, self.mvs)
 
-    def test_cast_i2f(self):
-        self.helper_primitives_1_params("cast_i2f", 2, 2.0)
+    def test_cast_float(self):
+        self.helper_primitives_1_params("cast_float", 2, 2.0)
 
-    def test_cast_i2s(self):
-        self.helper_primitives_1_params("cast_i2s", 2, "2")
+    def test_cast_string(self):
+        self.helper_primitives_1_params("cast_string", 2, "2")
 
-    def test_cast_i2b(self):
-        self.helper_primitives_1_params("cast_i2b", 2, True)
+    def test_cast_boolean(self):
+        self.helper_primitives_1_params("cast_boolean", 2, True)
 
-    def test_cast_f2i(self):
-        self.helper_primitives_1_params("cast_f2i", 2.4, 2)
+    def test_cast_integer(self):
+        self.helper_primitives_1_params("cast_integer", 2.4, 2)
 
-    def test_cast_f2s(self):
-        self.helper_primitives_1_params("cast_f2s", 2.4, "2.4")
+    def test_cast_string(self):
+        self.helper_primitives_1_params("cast_string", 2.4, "2.4")
 
-    def test_cast_f2b(self):
-        self.helper_primitives_1_params("cast_f2b", 2.4, True)
+    def test_cast_boolean(self):
+        self.helper_primitives_1_params("cast_boolean", 2.4, True)
 
-    def test_cast_s2i(self):
-        self.helper_primitives_1_params("cast_s2i", "2", 2)
+    def test_cast_integer(self):
+        self.helper_primitives_1_params("cast_integer", "2", 2)
 
-    def test_cast_s2f(self):
-        self.helper_primitives_1_params("cast_s2f", "2.4", 2.4)
+    def test_cast_float(self):
+        self.helper_primitives_1_params("cast_float", "2.4", 2.4)
 
-    def test_cast_s2b(self):
-        self.helper_primitives_1_params("cast_s2b", "2.4", True)
+    def test_cast_boolean(self):
+        self.helper_primitives_1_params("cast_boolean", "2.4", True)
 
-    def test_cast_b2i_true(self):
-        self.helper_primitives_1_params("cast_b2i", True, 1)
+    def test_cast_integer_true(self):
+        self.helper_primitives_1_params("cast_integer", True, 1)
 
-    def test_cast_b2f_true(self):
-        self.helper_primitives_1_params("cast_b2f", True, 1.0)
+    def test_cast_float_true(self):
+        self.helper_primitives_1_params("cast_float", True, 1.0)
 
-    def test_cast_b2s_true(self):
-        self.helper_primitives_1_params("cast_b2s", True, "True")
+    def test_cast_string_true(self):
+        self.helper_primitives_1_params("cast_string", True, "True")
 
-    def test_cast_b2i_false(self):
-        self.helper_primitives_1_params("cast_b2i", False, 0)
+    def test_cast_integer_false(self):
+        self.helper_primitives_1_params("cast_integer", False, 0)
 
-    def test_cast_b2f_false(self):
-        self.helper_primitives_1_params("cast_b2f", False, 0.0)
+    def test_cast_float_false(self):
+        self.helper_primitives_1_params("cast_float", False, 0.0)
 
-    def test_cast_b2s_false(self):
-        self.helper_primitives_1_params("cast_b2s", False, "False")
+    def test_cast_string_false(self):
+        self.helper_primitives_1_params("cast_string", False, "False")
 
-    def test_cast_e2s_node(self):
+    def test_cast_string_int(self):
         n = self.mvs.execute("CN", [])
-        self.helper_primitives_1_params("cast_e2s", n, "{ID: %s, value: None}" % n, t=True)
+        self.helper_primitives_1_params("cast_string", n, "None", t=True)
 
-    def test_cast_e2s_edge(self):
-        a = self.mvs.execute("CN", [])
-        b = self.mvs.execute("CN", [])
-        n = self.mvs.execute("CE", [a, b])
-        self.helper_primitives_1_params("cast_e2s", n, "{ID: %s, value: None}" % n, t=True)
-
-    def test_cast_e2s_value(self):
-        n = self.mvs.execute("CNV", [10])
-        self.helper_primitives_1_params("cast_e2s", n, "{ID: %s, value: 10}" % n, t=True)
-
-    def test_cast_v2s_int(self):
-        n = self.mvs.execute("CN", [])
-        self.helper_primitives_1_params("cast_v2s", n, "None", t=True)
+    def test_cast_string_int(self):
+        self.helper_primitives_1_params("cast_string", 2, "2")
 
-    def test_cast_v2s_int(self):
-        self.helper_primitives_1_params("cast_v2s", 2, "2")
+    def test_cast_string_neg_int(self):
+        self.helper_primitives_1_params("cast_string", -2, "-2")
 
-    def test_cast_v2s_neg_int(self):
-        self.helper_primitives_1_params("cast_v2s", -2, "-2")
+    def test_cast_string_float(self):
+        self.helper_primitives_1_params("cast_string", 2.0, "2.0")
 
-    def test_cast_v2s_float(self):
-        self.helper_primitives_1_params("cast_v2s", 2.0, "2.0")
+    def test_cast_string_neg_float(self):
+        self.helper_primitives_1_params("cast_string", -2.0, "-2.0")
 
-    def test_cast_v2s_neg_float(self):
-        self.helper_primitives_1_params("cast_v2s", -2.0, "-2.0")
+    def test_cast_string_string(self):
+        self.helper_primitives_1_params("cast_string", "abc", "abc")
 
-    def test_cast_v2s_string(self):
-        self.helper_primitives_1_params("cast_v2s", "abc", "\"abc\"")
+    def test_cast_string_string_stringnum(self):
+        self.helper_primitives_1_params("cast_value", "3", "\"3\"")
 
-    def test_cast_v2s_string_num(self):
-        self.helper_primitives_1_params("cast_v2s", "3", "\"3\"")
+    def test_cast_string_string_num(self):
+        self.helper_primitives_1_params("cast_value", 3, "3")
 
-    def test_cast_v2s_bool(self):
-        self.helper_primitives_1_params("cast_v2s", True, "true")
+    def test_cast_string_bool(self):
+        self.helper_primitives_1_params("cast_value", True, "true")
 
-    def test_cast_v2s_action(self):
-        self.helper_primitives_1_params("cast_v2s", {"value": "call"}, "call")
+    def test_cast_string_action(self):
+        self.helper_primitives_1_params("cast_value", {"value": "call"}, "call")
 
-    def test_cast_id2s_node(self):
+    def test_cast_id_node(self):
         n = self.mvs.execute("CN", [])
-        self.helper_primitives_1_params("cast_id2s", n, str(n), t=True)
+        self.helper_primitives_1_params("cast_id", n, str(n), t=True)
 
-    def test_cast_id2s_value(self):
+    def test_cast_id_value(self):
         n = self.mvs.execute("CNV", ["abc"])
-        self.helper_primitives_1_params("cast_id2s", n, str(n), t=True)
+        self.helper_primitives_1_params("cast_id", n, str(n), t=True)
 
-    def test_cast_id2s_edge(self):
+    def test_cast_id_edge(self):
         a = self.mvs.execute("CN", [])
         b = self.mvs.execute("CN", [])
         n = self.mvs.execute("CE", [a, b])
-        self.helper_primitives_1_params("cast_id2s", n, str(n), t=True)
+        self.helper_primitives_1_params("cast_id", n, str(n), t=True)
 
     def helper_primitives_1_params(self, operation, a, result, t=False):
         self.actual_arg_a = self.mvs.execute("CN", [])

+ 72 - 0
models/MM_render.mvc

@@ -0,0 +1,72 @@
+include "primitives.alh"
+
+SimpleAttribute Natural {}
+SimpleAttribute String {}
+SimpleAttribute Boolean {}
+
+Class GraphicalElement {
+    x : Natural
+    y : Natural
+    layer : Natural
+}
+
+Class Group : GraphicalElement {
+    __asid : String
+    dirty : Boolean
+}
+
+Association ConnectingLine (Group, Group) {
+    offsetSourceX : Natural
+    offsetSourceY : Natural
+    offsetTargetX : Natural
+    offsetTargetY : Natural
+    lineWidth : Natural
+    lineColour : String
+    arrow : Boolean
+    __asid : String
+    dirty : Boolean
+    layer : Natural
+}
+
+Class LineElement : GraphicalElement {
+    lineWidth : Natural
+    lineColour : String
+}
+
+Class Text : LineElement {
+    text : String
+}
+
+Class Line : LineElement {
+    targetX : Natural
+    targetY : Natural
+    arrow : Boolean
+}
+
+Class Shape : LineElement {
+    fillColour : String
+    width : Natural
+    height : Natural
+}
+
+Class Figure : GraphicalElement {
+    width : Natural
+    height : Natural
+}
+
+Class SVG {
+    data : String
+}
+
+Class Rectangle : Shape {
+}
+
+Class Ellipse : Shape {
+}
+
+Association contains (Group, GraphicalElement) {}
+Association renders (Figure, SVG) {
+    source_lower_cardinality = 1
+    target_lower_cardinality = 1
+    target_upper_cardinality = 1
+}

+ 1 - 1
models/SCCD_execute.alc

@@ -134,7 +134,7 @@ String function start_class(model : Element, data : Element, class : String, par
 
 	// First find an empty identifier
 	String identifier
-	identifier = cast_i2s(dict_len(data["classes"]))
+	identifier = cast_string(dict_len(data["classes"]))
 
 	// Create the data structure for a running class
 	Element class_handle

+ 3 - 3
models/epn_print.alc

@@ -17,7 +17,7 @@ Boolean function pn_print(model : Element):
 		name = read_attribute(model, place, "name")
 		tokens = read_attribute(model, place, "tokens")
 
-		log("  " + name + ": " + cast_v2s(tokens))
+		log("  " + name + ": " + cast_string(tokens))
 
 	log("Transitions:")
 	all_places = allInstances(model, "Encapsulated_PetriNet/Transition")
@@ -30,12 +30,12 @@ Boolean function pn_print(model : Element):
 		all_t = allIncomingAssociationInstances(model, place, "Encapsulated_PetriNet/P2T")
 		while (set_len(all_t) > 0):
 			t = set_pop(all_t)
-			log("    <-- " + cast_v2s(read_attribute(model, readAssociationSource(model, t), "name")))
+			log("    <-- " + cast_value(read_attribute(model, readAssociationSource(model, t), "name")))
 
 		all_t = allOutgoingAssociationInstances(model, place, "Encapsulated_PetriNet/T2P")
 		while (set_len(all_t) > 0):
 			t = set_pop(all_t)
-			log("    --> " + cast_v2s(read_attribute(model, readAssociationDestination(model, t), "name")))
+			log("    --> " + cast_value(read_attribute(model, readAssociationDestination(model, t), "name")))
 
 	log("Ports:")
 	all_places = allInstances(model, "Encapsulated_PetriNet/Port")

+ 1 - 1
models/merge_EPN.alc

@@ -12,5 +12,5 @@ Boolean function main(model : Element):
 		split = string_split(read_type(model, key), "/")
 		retype(model, key, string_join("Encapsulated_PetriNet/", split[1]))
 
-	//log("merge_EPN has seen # elements: " + cast_v2s(dict_len(model["model"])))
+	//log("merge_EPN has seen # elements: " + cast_value(dict_len(model["model"])))
 	return True!

+ 3 - 3
models/pn_print.alc

@@ -17,7 +17,7 @@ Boolean function pn_print(model : Element):
 		name = read_attribute(model, place, "name")
 		tokens = read_attribute(model, place, "tokens")
 
-		log("  " + name + ": " + cast_v2s(tokens))
+		log("  " + name + ": " + cast_string(tokens))
 
 	log("Transitions:")
 	all_places = allInstances(model, "PetriNet/Transition")
@@ -30,11 +30,11 @@ Boolean function pn_print(model : Element):
 		all_t = allIncomingAssociationInstances(model, place, "PetriNet/P2T")
 		while (set_len(all_t) > 0):
 			t = set_pop(all_t)
-			log("    <-- " + cast_v2s(read_attribute(model, readAssociationSource(model, t), "name")))
+			log("    <-- " + cast_value(read_attribute(model, readAssociationSource(model, t), "name")))
 
 		all_t = allOutgoingAssociationInstances(model, place, "PetriNet/T2P")
 		while (set_len(all_t) > 0):
 			t = set_pop(all_t)
-			log("    --> " + cast_v2s(read_attribute(model, readAssociationDestination(model, t), "name")))
+			log("    --> " + cast_value(read_attribute(model, readAssociationDestination(model, t), "name")))
 
 	return True!

+ 6 - 6
models/reachability.alc

@@ -77,8 +77,8 @@ Boolean function reachability_graph(model : Element):
 	set_add(workset, state_id)
 
 	// And add in the model itself
-	state = instantiate_node(model, "ReachabilityGraph/InitialState", cast_i2s(state_id))
-	instantiate_attribute(model, state, "name", cast_i2s(state_id))
+	state = instantiate_node(model, "ReachabilityGraph/InitialState", cast_string(state_id))
+	instantiate_attribute(model, state, "name", cast_string(state_id))
 	instantiate_attribute(model, state, "error", False)
 	keys = dict_keys(dict_repr)
 	while (set_len(keys) > 0):
@@ -148,8 +148,8 @@ Boolean function reachability_graph(model : Element):
 					set_add(workset, target_id)
 
 					// And add in the model itself
-					state = instantiate_node(model, "ReachabilityGraph/State", cast_i2s(target_id))
-					instantiate_attribute(model, state, "name", cast_i2s(target_id))
+					state = instantiate_node(model, "ReachabilityGraph/State", cast_string(target_id))
+					instantiate_attribute(model, state, "name", cast_string(target_id))
 					instantiate_attribute(model, state, "error", False)
 
 					keys = dict_keys(new_dict_repr)
@@ -174,8 +174,8 @@ Boolean function reachability_graph(model : Element):
 				dict_add_fast(mappings[state_id], transition, target_id)
 
 				// And also store it in the model itself
-				new_transition = instantiate_link(model, "ReachabilityGraph/Transition", "", cast_i2s(state_id), cast_i2s(target_id))
+				new_transition = instantiate_link(model, "ReachabilityGraph/Transition", "", cast_string(state_id), cast_string(target_id))
 				instantiate_attribute(model, new_transition, "name", read_attribute(model, transition, "name"))
 
-	log("# reachable states: " + cast_v2s(next_id))
+	log("# reachable states: " + cast_value(next_id))
 	return True!

+ 2 - 2
models/reachabilitygraph_print.mvc

@@ -24,7 +24,7 @@ Composite schedule {
                         while (set_len(all_values) > 0):
                             place = set_pop(all_values)
                             dict_add(dict_values, read_attribute(model, place, "name"), read_attribute(model, place, "tokens"))
-                        output(cast_v2s(read_attribute(model, name, "name")) + ": " + dict_to_string(dict_values))
+                        output(cast_string(read_attribute(model, name, "name")) + ": " + dict_to_string(dict_values))
                         return!
                     $
             }
@@ -54,7 +54,7 @@ Composite schedule {
                 label = "2"
                 action = $
                     Void function action(model : Element, name : String, mapping : Element):
-                        output(cast_v2s(read_attribute(model, mapping["0"], "name")) + " --[" + cast_v2s(read_attribute(model, name, "name")) + "]--> " + cast_v2s(read_attribute(model, mapping["1"], "name")))
+                        output(cast_string(read_attribute(model, mapping["0"], "name")) + " --[" + cast_string(read_attribute(model, name, "name")) + "]--> " + cast_string(read_attribute(model, mapping["1"], "name")))
                         return!
                     $
             }

+ 213 - 0
models/render_OD.alc

@@ -0,0 +1,213 @@
+include "primitives.alh"
+include "modelling.alh"
+include "object_operations.alh"
+
+Boolean function main(model : Element):
+	Element elements
+	String class
+	Element attrs
+	Element attr_keys
+	String attr_key
+	String group
+	String elem
+	Integer loc_x
+	Integer loc_y
+	Integer text_loc
+	loc_x = 10
+	loc_y = 10
+
+	Element to_remove
+	String elem_to_remove
+	Element groups
+	Element class_types
+	Element metamodel
+	metamodel = model["metamodel"]
+	String class_type
+
+	// Construct our own kind of tracability
+	Element cs_to_as
+	Element as_to_cs
+	String asid
+	cs_to_as = dict_create()
+	as_to_cs = dict_create()
+	groups = allInstances(model, "rendered/Group")
+	while (set_len(groups) > 0):
+		group = set_pop(groups)
+		asid = read_attribute(model, group, "__asid")
+		dict_add(cs_to_as, group, "abstract/" + asid)
+		dict_add(as_to_cs, "abstract/" + asid, group)
+
+	// Now render everything
+	groups = dict_create()
+	class_types = allInstances(metamodel, "Class")
+	while (set_len(class_types) > 0):
+		class_type = set_pop(class_types)
+
+		if (string_startswith(class_type, "abstract/")):
+			elements = allInstances(model, class_type)
+
+			while (set_len(elements) > 0):
+				class = set_pop(elements)
+
+				if (is_edge(model["model"][class])):
+					continue!
+				
+				Integer x
+				Integer y
+				x = loc_x
+				y = loc_y
+
+				// Check if there is already an associated element
+				if (dict_in(as_to_cs, class)):
+					// Yes, but is it still clean?
+					Element related_groups
+					group = as_to_cs[class]
+
+					if (bool_not(read_attribute(model, group, "dirty"))):
+						dict_add(groups, class, group)
+						continue!
+					else:
+						group = as_to_cs[class]
+						to_remove = allAssociationDestinations(model, group, "rendered/contains")
+						x = create_value(read_attribute(model, group, "x"))
+						y = create_value(read_attribute(model, group, "y"))
+
+						while (set_len(to_remove) > 0):
+							elem_to_remove = set_pop(to_remove)
+							if (read_type(model, elem_to_remove) == "rendered/Group"):
+								set_add(to_remove, elem_to_remove)
+							else:
+								model_delete_element(model, elem_to_remove)
+						model_delete_element(model, group)
+						dict_delete(as_to_cs, class)
+
+				if (dict_in(groups, class)):
+					// Already rendered this, so skip
+					continue!
+
+				text_loc = 5
+
+				group = instantiate_node(model, "rendered/Group", "")
+				instantiate_attribute(model, group, "x", x)
+				instantiate_attribute(model, group, "y", y)
+				instantiate_attribute(model, group, "__asid", list_read(string_split(class, "/"), 1))
+				instantiate_attribute(model, group, "layer", 0)
+				dict_add(groups, class, group)
+
+				loc_x = loc_x + 250
+				if (loc_x > 2000):
+					loc_x = 10
+					loc_y = loc_y + 300
+
+				elem = instantiate_node(model, "rendered/Rectangle", "")
+				instantiate_attribute(model, elem, "x", 0)
+				instantiate_attribute(model, elem, "y", 0)
+				instantiate_attribute(model, elem, "height", 40 + set_len(getAttributes(model, class)) * 20)
+				instantiate_attribute(model, elem, "width", 200)
+				instantiate_attribute(model, elem, "lineWidth", 2) 
+				instantiate_attribute(model, elem, "lineColour", "black")
+				instantiate_attribute(model, elem, "fillColour", "white")
+				instantiate_attribute(model, elem, "layer", 1)
+				instantiate_link(model, "rendered/contains", "", group, elem)
+
+				elem = instantiate_node(model, "rendered/Text", "")
+				instantiate_attribute(model, elem, "x", 5)
+				instantiate_attribute(model, elem, "y", 3)
+				instantiate_attribute(model, elem, "lineWidth", 1)
+				instantiate_attribute(model, elem, "lineColour", "black")
+				instantiate_attribute(model, elem, "text", string_join(cast_value(list_read(string_split(class, "/"), 1)), " : " + cast_value(list_read(string_split(read_type(model, class), "/"), 1))))
+				instantiate_attribute(model, elem, "layer", 2)
+				instantiate_link(model, "rendered/contains", "", group, elem)
+
+				elem = instantiate_node(model, "rendered/Line", "")
+				instantiate_attribute(model, elem, "x", 0)
+				instantiate_attribute(model, elem, "y", 20)
+				instantiate_attribute(model, elem, "targetX", 200)
+				instantiate_attribute(model, elem, "targetY", 20)
+				instantiate_attribute(model, elem, "lineWidth", 1)
+				instantiate_attribute(model, elem, "lineColour", "black")
+				instantiate_attribute(model, elem, "arrow", False)
+				instantiate_attribute(model, elem, "layer", 2)
+				instantiate_link(model, "rendered/contains", "", group, elem)
+
+				attrs = getAttributes(model, class)
+				attr_keys = dict_keys(attrs)
+				while (dict_len(attr_keys) > 0):
+					attr_key = set_pop(attr_keys)
+					elem = instantiate_node(model, "rendered/Text", "")
+					instantiate_attribute(model, elem, "x", 5)
+					instantiate_attribute(model, elem, "y", text_loc + 20)
+					instantiate_attribute(model, elem, "lineWidth", 1)
+					instantiate_attribute(model, elem, "lineColour", "black")
+					instantiate_attribute(model, elem, "text", (attr_key + " = ") + cast_value(attrs[attr_key]))
+					instantiate_attribute(model, elem, "layer", 2)
+					instantiate_link(model, "rendered/contains", "", group, elem)
+					text_loc = text_loc + 15
+
+	// Flush all associations
+	elements = allInstances(model, "rendered/ConnectingLine")
+	while (set_len(elements) > 0):
+		class = set_pop(elements)
+		model_delete_element(model, class)
+
+	// Rerender associations
+	Element to_render
+	to_render = set_create()
+	class_types = allInstances(metamodel, "Association")
+	while (set_len(class_types) > 0):
+		class_type = set_pop(class_types)
+		log("Checking type " + class_type)
+
+		if (string_startswith(class_type, "abstract/")):
+			elements = allInstances(model, class_type)
+			log("    Checking instance " + class)
+			while (set_len(elements) > 0):
+				class = set_pop(elements)
+				if (is_edge(model["model"][class])):
+					if (bool_not(set_in(to_render, class))):
+						set_add(to_render, class)
+						log("Added!")
+
+	to_render = set_to_list(to_render)
+	Element delayed_elements
+	Integer num_to_render
+	delayed_elements = list_create()
+	while (list_len(to_render) > 0):
+		num_to_render = list_len(to_render)
+		while (list_len(to_render) > 0):
+			class = list_pop_final(to_render)
+			attr_keys = dict_keys(getAttributes(model, class))
+
+			if (bool_not(bool_and(dict_in(groups, readAssociationSource(model, class)), dict_in(groups, readAssociationDestination(model, class))))):
+				list_append(delayed_elements, class)
+				continue!
+
+			elem = instantiate_link(model, "rendered/ConnectingLine", "", groups[readAssociationSource(model, class)], groups[readAssociationDestination(model, class)])
+			dict_add(groups, class, elem)
+			if (is_edge(model["model"][readAssociationSource(model, class)])):
+				instantiate_attribute(model, elem, "offsetSourceX", 0)
+				instantiate_attribute(model, elem, "offsetSourceY", 0)
+			else:
+				instantiate_attribute(model, elem, "offsetSourceX", 100)
+				instantiate_attribute(model, elem, "offsetSourceY", 30)
+			if (is_edge(model["model"][readAssociationDestination(model, class)])):
+				instantiate_attribute(model, elem, "offsetTargetX", 0)
+				instantiate_attribute(model, elem, "offsetTargetY", 0)
+			else:
+				instantiate_attribute(model, elem, "offsetTargetX", 100)
+				instantiate_attribute(model, elem, "offsetTargetY", 30)
+			instantiate_attribute(model, elem, "lineWidth", 3)
+			instantiate_attribute(model, elem, "lineColour", "black")
+			instantiate_attribute(model, elem, "arrow", True)
+			instantiate_attribute(model, elem, "__asid", list_read(string_split(class, "/"), 1))
+			instantiate_attribute(model, elem, "layer", 0)
+			instantiate_link(model, "rendered/contains", "", group, elem)
+
+		if (num_to_render == list_len(delayed_elements)):
+			log("Could not decrease number of rendered elements anymore... Giving up!")
+			return True!
+		else:
+			to_render = delayed_elements
+			delayed_elements = list_create()
+
+	return True!

+ 182 - 0
models/render_SCD.alc

@@ -0,0 +1,182 @@
+include "primitives.alh"
+include "modelling.alh"
+include "object_operations.alh"
+
+Boolean function main(model : Element):
+	Element elements
+	String class
+	Element attrs
+	Element attr_keys
+	String attr_key
+	String group
+	String elem
+	Integer loc
+	Integer text_loc
+	Element related_groups
+	loc = 10
+
+	Element groups
+	groups = dict_create()
+
+	elements = allInstances(model, "rendered/Group")
+	while (set_len(elements) > 0):
+		group = set_pop(elements)
+		if (set_len(allIncomingAssociationInstances(model, group, "TracabilityClass")) == 0):
+			Element to_remove
+			String elem_to_remove
+			to_remove = allAssociationDestinations(model, group, "rendered/contains")
+			while (set_len(to_remove) > 0):
+				elem_to_remove = set_pop(to_remove)
+				if (read_type(model, elem_to_remove) == "rendered/Group"):
+					set_add(to_remove, elem_to_remove)
+				else:
+					model_delete_element(model, elem_to_remove)
+			model_delete_element(model, group)
+
+	elements = allInstances(model, "abstract/Class")
+	while (set_len(elements) > 0):
+		class = set_pop(elements)
+		
+		Integer x
+		Integer y
+		x = loc
+		y = 10
+
+		// Check if there is already an associated element
+		if (set_len(allOutgoingAssociationInstances(model, class, "TracabilityClass")) > 0):
+			// Yes, but is it still clean?
+			Boolean dirty
+			dirty = False
+
+			related_groups = allAssociationDestinations(model, class, "TracabilityClass")
+			while (set_len(related_groups) > 0):
+				group = set_pop(related_groups)
+				if (value_eq(read_attribute(model, group, "dirty"), True)):
+					// No, so mark all as dirty
+					dirty = True
+					break!
+				else:
+					// Yes, so just ignore this!
+					continue!
+
+			if (bool_not(dirty)):
+				dict_add(groups, class, group)
+				continue!
+			else:
+				related_groups = allAssociationDestinations(model, class, "TracabilityClass")
+				Element to_remove
+				String elem_to_remove
+				while (set_len(related_groups) > 0):
+					group = set_pop(related_groups)
+					to_remove = allAssociationDestinations(model, group, "rendered/contains")
+					x = create_value(read_attribute(model, group, "x"))
+					y = create_value(read_attribute(model, group, "y"))
+					while (set_len(to_remove) > 0):
+						elem_to_remove = set_pop(to_remove)
+						if (read_type(model, elem_to_remove) == "rendered/Group"):
+							set_add(to_remove, elem_to_remove)
+						else:
+							model_delete_element(model, elem_to_remove)
+					model_delete_element(model, group)
+
+		attr_keys = dict_keys(getAttributeList(model, class))
+		text_loc = 5
+
+		group = instantiate_node(model, "rendered/Group", "")
+		instantiate_attribute(model, group, "x", x)
+		instantiate_attribute(model, group, "y", y)
+		instantiate_attribute(model, group, "__asid", list_read(string_split(class, "/"), 1))
+		instantiate_attribute(model, group, "layer", 0)
+		dict_add(groups, class, group)
+		loc = loc + 200
+
+		elem = instantiate_node(model, "rendered/Rectangle", "")
+		instantiate_attribute(model, elem, "x", 0)
+		instantiate_attribute(model, elem, "y", 0)
+		instantiate_attribute(model, elem, "height", 40 + set_len(getInstantiatableAttributes(model, class, "abstract/AttributeLink")) * 20)
+		instantiate_attribute(model, elem, "width", 150)
+		instantiate_attribute(model, elem, "lineWidth", 2) 
+		instantiate_attribute(model, elem, "lineColour", "black")
+		instantiate_attribute(model, elem, "fillColour", "white")
+		instantiate_attribute(model, elem, "layer", 1)
+		instantiate_link(model, "rendered/contains", "", group, elem)
+
+		String multiplicities
+		String lower_card
+		String upper_card
+		if (element_eq(read_attribute(model, class, "lower_cardinality"), read_root())):
+			lower_card = "*"
+		else:
+			lower_card = cast_value(read_attribute(model, class, "lower_cardinality"))
+		if (element_eq(read_attribute(model, class, "upper_cardinality"), read_root())):
+			upper_card = "*"
+		else:
+			upper_card = cast_value(read_attribute(model, class, "upper_cardinality"))
+		multiplicities = ((("[" + lower_card) + "..") + upper_card) + "]"
+
+		elem = instantiate_node(model, "rendered/Text", "")
+		instantiate_attribute(model, elem, "x", 5)
+		instantiate_attribute(model, elem, "y", 3)
+		instantiate_attribute(model, elem, "lineWidth", 1)
+		instantiate_attribute(model, elem, "lineColour", "black")
+		if (element_neq(read_attribute(model, class, "name"), read_root())):
+			instantiate_attribute(model, elem, "text", string_join(read_attribute(model, class, "name"), "  " + multiplicities))
+		else:
+			instantiate_attribute(model, elem, "text", "(unnamed) " + multiplicities)
+		instantiate_attribute(model, elem, "layer", 2)
+		instantiate_link(model, "rendered/contains", "", group, elem)
+
+		elem = instantiate_node(model, "rendered/Line", "")
+		instantiate_attribute(model, elem, "x", 0)
+		instantiate_attribute(model, elem, "y", 20)
+		instantiate_attribute(model, elem, "targetX", 150)
+		instantiate_attribute(model, elem, "targetY", 20)
+		instantiate_attribute(model, elem, "lineWidth", 1)
+		instantiate_attribute(model, elem, "lineColour", "black")
+		instantiate_attribute(model, elem, "arrow", False)
+		instantiate_attribute(model, elem, "layer", 2)
+		instantiate_link(model, "rendered/contains", "", group, elem)
+
+		attrs = getInstantiatableAttributes(model, class, "abstract/AttributeLink")
+		attr_keys = dict_keys(attrs)
+		while (dict_len(attr_keys) > 0):
+			attr_key = set_pop(attr_keys)
+			elem = instantiate_node(model, "rendered/Text", "")
+			instantiate_attribute(model, elem, "x", 5)
+			instantiate_attribute(model, elem, "y", text_loc + 20)
+			instantiate_attribute(model, elem, "lineWidth", 1)
+			instantiate_attribute(model, elem, "lineColour", "black")
+			instantiate_attribute(model, elem, "text", (attr_key + " : ") + cast_string(list_read(string_split(attrs[attr_key], "/"), 1)))
+			instantiate_attribute(model, elem, "layer", 2)
+			instantiate_link(model, "rendered/contains", "", group, elem)
+			text_loc = text_loc + 15
+
+		instantiate_link(model, "TracabilityClass", "", class, group)
+
+	// Flush all associations
+	elements = allInstances(model, "rendered/ConnectingLine")
+	while (set_len(elements) > 0):
+		class = set_pop(elements)
+		model_delete_element(model, class)
+
+	// Rerender associations
+	elements = allInstances(model, "abstract/Association")
+	while (set_len(elements) > 0):
+		class = set_pop(elements)
+
+		attr_keys = dict_keys(getAttributeList(model, class))
+
+		elem = instantiate_link(model, "rendered/ConnectingLine", "", groups[readAssociationSource(model, class)], groups[readAssociationDestination(model, class)])
+		instantiate_attribute(model, elem, "offsetSourceX", 75)
+		instantiate_attribute(model, elem, "offsetSourceY", 30)
+		instantiate_attribute(model, elem, "offsetTargetX", 75)
+		instantiate_attribute(model, elem, "offsetTargetY", 30)
+		instantiate_attribute(model, elem, "lineWidth", 1)
+		instantiate_attribute(model, elem, "lineColour", "black")
+		instantiate_attribute(model, elem, "arrow", True)
+		instantiate_attribute(model, elem, "__asid", list_read(string_split(class, "/"), 1))
+		instantiate_attribute(model, elem, "layer", 0)
+		log("Found ASID " + cast_value(list_read(string_split(class, "/"), 1)))
+		instantiate_link(model, "rendered/contains", "", group, elem)
+
+	return True!

+ 25 - 0
models/test_compiler.alc

@@ -0,0 +1,25 @@
+include "compiler.alh"
+include "primitives.alh"
+
+Void function main(model : Element):
+	String code
+	code = ""
+	code = code + "include \"primitives.alh\"\n"
+	code = code + "Void function test_function():\n"
+	code = code + "    log(\"Function!\")\n"
+	code = code + "    abcd\n"
+	code = code + "    return!"
+
+	log("Got code: ")
+	log(code)
+	
+	Element result
+	result = compile_code(code)
+
+	log("Executing result: " + cast_value(result))
+	if (element_eq(result, read_root())):
+		log("ERROR: compilation error")
+	else:
+		result()
+
+	return!

+ 3 - 3
wrappers/test_modelverse.py

@@ -43,9 +43,9 @@ transformation_add_AL({"B": "MetamodelB", "C": "MetamodelC"}, {"B": "MetamodelB"
     include "modelling.alh"
 
     Boolean function size_of_model(model : Element):
-        log("Number of instances of A: " + cast_v2s(set_len(allInstances(model, "A/A"))))
-        log("Number of instances of B: " + cast_v2s(set_len(allInstances(model, "B/B"))))
-        log("Number of instances of C: " + cast_v2s(set_len(allInstances(model, "C/C"))))
+        log("Number of instances of A: " + cast_value(set_len(allInstances(model, "A/A"))))
+        log("Number of instances of B: " + cast_value(set_len(allInstances(model, "B/B"))))
+        log("Number of instances of C: " + cast_value(set_len(allInstances(model, "C/C"))))
         return True!
     """
     )