include "primitives.alh" include "io.alh" include "object_operations.alh" include "constructors.alh" include "metamodels.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 if (bool_not(dict_in(model["model"], source))): log("In link " + name) log("ERROR: source of link unknown: " + source) log("Destination: " + destination) return "" if (bool_not(dict_in(model["model"], destination))): log("In link " + name) log("ERROR: destination of link unknown: " + destination) log("Source: " + source) return "" 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 String function find_attribute_type(model : Element, elem : String, name : String): String mm_elem String direct_type direct_type = reverseKeyLookup(model["metamodel"]["model"], dict_read_node(model["type_mapping"], model["model"][elem])) mm_elem = find_attribute_definer(model["metamodel"], direct_type, name) if (value_eq(mm_elem, "")): // Couldn't find element, so is not allowed! return "" else: return reverseKeyLookup(model["metamodel"]["model"], dict_read_edge(model["metamodel"]["model"][mm_elem], name)) Element function get_superclasses(model : Element, name : String): Element result Integer i Integer num_edges Element edge Element elem elem = model["model"][name] // 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, reverseKeyLookup(model["model"], read_edge_dst(edge))) i = i + 1 return result String function find_attribute_definer(model : Element, elem_name : String, name : String): if (dict_in(model["model"][elem_name], name)): // Try in the current class definition return elem_name else: // Not found, so go to all superclasses and try there Element superclasses Element current Element found superclasses = get_superclasses(model, elem_name) while (list_len(superclasses) > 0): current = set_pop(superclasses) found = find_attribute_definer(model, current, name) if (bool_not(value_eq(found, ""))): // Found something! return current // Error return "" 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) if (attr_type == ""): log("Could not find attribute!") return attr_name = model_add_value(model, "", value) retype(model, attr_name, reverseKeyLookup(model["metamodel"]["model"], 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): Integer i Integer count Element edge Element edge_type Element elem Element typing elem = model["model"][element] typing = model["type_mapping"] count = read_nr_out(elem) i = 0 while (i < count): edge = read_out(elem, i) if (dict_in_node(typing, edge)): edge_type = dict_read_node(typing, edge) if (element_eq(edge_type, dict_read_edge(read_edge_src(edge_type), attribute))): return read_edge_dst(edge) i = i + 1 return read_root() Void function unset_attribute(model : Element, element : String, attribute : String): // Removes an attribute if it exists String attr_type Element attr_links String attr_link attr_type = find_attribute_type(model, element, attribute) attr_links = allOutgoingAssociationInstances(model, element, attr_type) while (list_len(attr_links) > 0): attr_link = set_pop(attr_links) dict_delete(model["type_mapping"], read_edge_dst(model["model"][attr_link])) dict_delete(model["type_mapping"], model["model"][attr_link]) delete_element(read_edge_dst(model["model"][attr_link])) return Void function add_AL_links(model : Element, list : Element, element : Element, type: String, linkname : String, expected_type : String): if (bool_not(dict_in(element, linkname))): return Element link link = dict_read_edge(element, linkname) // The link dict_add(model["model"], "__" + cast_id2s(link), link) dict_add(model["type_mapping"], link, model["metamodel"]["model"][(type + "_") + linkname]) // The name link link = read_out(link, 0) dict_add(model["model"], "__" + cast_id2s(link), link) dict_add(model["type_mapping"], link, model["metamodel"]["model"]["to_str"]) // The name node link = read_edge_dst(link) if (bool_not(set_in_node(model["model"], link))): dict_add(model["model"], "__" + cast_id2s(link), link) dict_add(model["type_mapping"], link, model["metamodel"]["model"]["String"]) // 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) return String function add_AL(model : Element, element : Element): Element todo Element node Element work_node Element elem String type todo = create_node() node = create_node() list_append(node, element) list_append(node, "funcdef") set_add(todo, node) while (0 < dict_len(todo)): work_node = set_pop(todo) elem = list_read(work_node, 0) type = list_read(work_node, 1) if (bool_not(set_in_node(model["model"], elem))): // Determine the type if we don't know it if (type == ""): if (is_physical_action(elem)): type = cast_a2s(elem) else: type = "Any" // Add the node itself dict_add(model["model"], "__" + cast_id2s(elem), elem) dict_add(model["type_mapping"], elem, model["metamodel"]["model"][type]) // Now add its edges if (type == "if"): add_AL_links(model, todo, elem, type, "cond", "") add_AL_links(model, todo, elem, type, "true", "") add_AL_links(model, todo, elem, type, "false", "") add_AL_links(model, todo, elem, type, "next", "") elif (type == "while"): add_AL_links(model, todo, elem, type, "cond", "") 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, "value", "") add_AL_links(model, todo, elem, type, "next", "") elif (type == "break"): add_AL_links(model, todo, elem, type, "while", "while") elif (type == "continue"): add_AL_links(model, todo, elem, type, "while", "while") elif (type == "return"): add_AL_links(model, todo, elem, type, "value", "") elif (type == "resolve"): add_AL_links(model, todo, elem, type, "var", "") elif (type == "access"): add_AL_links(model, todo, elem, type, "var", "") elif (type == "constant"): add_AL_links(model, todo, elem, type, "node", "") elif (type == "output"): add_AL_links(model, todo, elem, type, "node", "") add_AL_links(model, todo, elem, type, "next", "") elif (type == "global"): add_AL_links(model, todo, elem, type, "var", "String") add_AL_links(model, todo, elem, type, "next", "") elif (type == "param"): add_AL_links(model, todo, elem, type, "name", "String") add_AL_links(model, todo, elem, type, "value", "") add_AL_links(model, todo, elem, type, "next_param", "param") elif (type == "funcdef"): add_AL_links(model, todo, elem, type, "body", "") add_AL_links(model, todo, elem, type, "next", "") elif (type == "call"): add_AL_links(model, todo, elem, type, "func", "") add_AL_links(model, todo, elem, type, "params", "param") 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 constraint_name = add_AL(model, constraint) attr_type = find_attribute_type(model, element, "constraint") instantiate_link(model, attr_type, "", element, constraint_name) return Void function construct_model(): String command 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()) elif (command == "add_constraint"): add_constraint(input(), input(), construct_function()) elif (command == "initialize_SCD"): initialize_SCD(input()) elif (command == "initialize_bottom"): initialize_bottom(input()) else: log("Modelling error: did not understand command " + command)