include "primitives.alh" include "io.alh" include "object_operations.alh" String function instantiated_name(element : Element, original : String): if (original == ""): return "__" + cast_id2s(element) else: return original Element function instantiate_bottom(): // Just create a new node that serves as the basis for everything // We don't know anything about the model yet, so just create an empty one Element new_model // The actual root node of the model new_model = create_node() // Add an empty model and empty type mapping dict_add(new_model, "model", create_node()) dict_add(new_model, "type_mapping", create_node()) // Return the created model return new_model String function model_add_node(model : Element, name : String): // Adds a new node to the specified model with the desired name // This is a bottom operation, as it doesn't take any type Element new_node String actual_name new_node = create_node() actual_name = instantiated_name(new_node, name) dict_add(model["model"], actual_name, new_node) return actual_name String function model_add_value(model : Element, name : String, value : Element): // Similar to model_add_node, but add a value as well String actual_name actual_name = instantiated_name(value, name) dict_add(model["model"], actual_name, value) return actual_name String function model_add_edge(model : Element, name : String, source : String, destination : String): // Add an edge between the source and destination nodes // Nodes are specified using their string representation previously defined Element new_edge String actual_name new_edge = create_edge(model["model"][source], model["model"][destination]) actual_name = instantiated_name(new_edge, name) dict_add(model["model"], actual_name, new_edge) return actual_name Void function retype_model(model : Element, metamodel : Element): // Remove the type mapping and add a new one for the specified metamodel dict_delete(model, "type_mapping") dict_add(model, "type_mapping", create_node()) dict_add(model, "metamodel", metamodel) return Void function retype(model : Element, element : String, type : String): // Retype a model, deleting any previous type the element had // The type string is evaluated in the metamodel previously specified if (dict_in_node(model["type_mapping"], model["model"][element])): dict_delete(model["type_mapping"], model["model"][element]) dict_add(model["type_mapping"], model["model"][element], model["metamodel"]["model"][type]) return Element function instantiate_model(metamodel : Element): // Instantiate a model // Basically create an untyped model and retype it Element model model = instantiate_bottom() retype_model(model, metamodel) return model String function instantiate_node(model : Element, type_name : String, instance_name : String): // Create a node typed by a node from the metamodel // Basically create a node and type it immediately String actual_name actual_name = model_add_node(model, instance_name) retype(model, instance_name, type_name) return actual_name Element function find_attribute_type(model : Element, elem : String, name : String): Element mm_elem Element direct_type direct_type = dict_read_node(model["type_mapping"], model["model"][elem]) mm_elem = find_attribute_definer(model["metamodel"], direct_type, name) if (element_eq(mm_elem, read_root())): // Couldn't find element, so is not allowed! return read_root() else: return getName(model["metamodel"], dict_read_edge(mm_elem, name)) Element function get_superclasses(model : Element, elem : Element): Element result Integer i Integer num_edges Element edge // Initialize empty set result = create_node() i = 0 // Read out all outgoing edges num_edges = read_nr_out(elem) while (i < num_edges): edge = read_out(elem, i) if (element_eq(dict_read_node(model["type_mapping"], edge), model["inheritance"])): create_edge(result, read_edge_dst(edge)) i = i + 1 return result Element function find_attribute_definer(model : Element, elem : Element, name : String): if (dict_in(elem, name)): // Try in the current class definition return elem else: // Not found, so go to all superclasses and try there Element superclasses Element current Element found superclasses = get_superclasses(model, elem) while (list_len(superclasses) > 0): current = set_pop(superclasses) found = find_attribute_definer(model, current, name) if (bool_not(element_eq(found, read_root()))): // Found something! return current // Return the de facto error-value return read_root() Void function instantiate_attribute(model : Element, element : String, attribute_name : String, value : Element): // Instantiate an attribute of something that needs to be instantiated // Actually a bit more difficult than all the rest, as we need to find the attribute to instantiate String attr_type String attr_name attr_type = find_attribute_type(model, element, attribute_name) attr_name = model_add_value(model, "", value) retype(model, attr_name, getName(model["metamodel"], read_edge_dst(model["metamodel"]["model"][attr_type]))) instantiate_link(model, attr_type, "", element, attr_name) return String function instantiate_link(model : Element, type : String, name : String, source : String, destination : String): // Create a typed link between two nodes String actual_name actual_name = model_add_edge(model, name, source, destination) retype(model, actual_name, type) return actual_name Void function define_inheritance(model : Element, inheritance_name : String): // Set the inheritance link to the one defined in our own metamodel, given by the specified name dict_add(model, "inheritance", model["metamodel"]["model"][inheritance_name]) return Void function model_delete_element(model : Element, name : String): // Remove the link // 1) from the type mapping dict_delete(model["type_mapping"], model["model"][name]) // 2) from the model delete_element(model["model"][name]) return Element function read_attribute(model : Element, element : String, attribute : String): // Read out the value of an attribute Element attr_type Element attr_links Element attr_link attr_type = find_attribute_type(model, element, attribute) attr_links = allOutgoingAssociationInstances(model, model["model"][element], model["metamodel"]["model"][attr_type]) while (list_len(attr_links) > 0): attr_link = set_pop(attr_links) return read_edge_dst(attr_link) return read_root() Void function unset_attribute(model : Element, element : String, attribute : String): // Removes an attribute if it exists Element attr_type Element attr_links Element attr_link attr_type = find_attribute_type(model, element, attribute) attr_links = allOutgoingAssociationInstances(model, model["model"][element], model["metamodel"]["model"][attr_type]) while (list_len(attr_links) > 0): attr_link = set_pop(attr_links) model_delete_element(model, getName(model, attr_link)) return Void function construct_model(): String command log("Enter modelling constructs!") while (True): command = input() if (command == "instantiate_bottom"): output(instantiate_bottom()) elif (command == "add_node"): model_add_node(input(), input()) elif (command == "add_value"): model_add_value(input(), input(), input()) elif (command == "add_edge"): model_add_edge(input(), input(), input(), input()) elif (command == "exit"): return elif (command == "retype_model"): retype_model(input(), input()) elif (command == "retype"): retype(input(), input(), input()) elif (command == "instantiate_model"): output(instantiate_model(input())) elif (command == "instantiate_node"): instantiate_node(input(), input(), input()) elif (command == "instantiate_attribute"): instantiate_attribute(input(), input(), input(), input()) elif (command == "instantiate_link"): instantiate_link(input(), input(), input(), input(), input()) elif (command == "define_inheritance"): define_inheritance(input(), input()) else: log("Modelling error: did not understand command " + command)