include "primitives.alh" include "io.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 Void function instantiate_attribute(model : Element, element : String, attribute : 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 Element elem Element type Element attr_type elem = model["model"][element] type = model["type_mapping"][elem] //attr_type = find_attribute(model, type, attribute) instantiate_link(model, attr_type, "", elem, value) 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 instantiate_named_value(model : Element, type : String, name : String, source : String, destination : Element): // Special helper function to create an edge and name it String actual_name actual_name = instantiate_link(model, type, "", source, destination) instantiate_attribute(model, model["model"][actual_name], "name", name) return Void function instantiate_named(model : Element, type : String, name : String, source : String, destination : String): // Special helper function to create an edge and name it instantiate_named(model, type, name, source, model["model"][destination]) return 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 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_attribute"): instantiate_named(input(), input(), input(), input(), input()) elif (command == "define_inheritance"): define_inheritance(input(), input()) else: log("Modelling error: did not understand command " + command)