import time def get_superclasses(a, b, **remainder): if 'value' not in b: b['value'], = yield [("RV", [b['id']])] model_dict, tm_dict = yield [("RD", [a['id'], "model"]), ("RD", [a['id'], "type_mapping"])] worklist = set([b['value']]) found = set([]) cache_value = {} while worklist: name = worklist.pop() if name in found: continue elem, = yield [("RD", [model_dict, name])] found.add(name) # Iterate over all outgoing links if elem is None: print("ERROR: " + str(locals())) outgoing, = yield [("RO", [elem])] outgoing = set(outgoing) while (outgoing): link = outgoing.pop() # If the link is typed by "Inheritance", we add its destination link_name_node, = yield [("CALL_ARGS", [reverseKeyLookup, [{'id': model_dict}, {'id': link}]])] if "value" not in link_name_node: link_name_node['value'], = yield [("RV", [link_name_node['id']])] t_edge, = yield [("RD", [tm_dict, link_name_node['value']])] t_edge, = yield [("RV", [t_edge])] if t_edge == "Inheritance": edge, = yield [("RE", [link])] src, dst = edge # Look up dst's name and add it if dst not in cache_value: dst_name, = yield [("CALL_ARGS", [reverseKeyLookup, [{'id': model_dict}, {'id': dst}]])] if 'value' not in dst_name: dst_name['value'], = yield [("RV", [dst_name['id']])] cache_value[dst] = dst_name['value'] dst_name_value = cache_value[dst] worklist.add(dst_name_value) result, = yield [("CN", [])] yield [("CD", [result, i, result]) for i in found] yield [("RETURN", [{'id': result}])] def reverseKeyLookupMultiID(a, b, **remainder): edges, result = yield [("RO", [a['id']]), ("CN", [])] expanded_edges = yield [("RE", [i]) for i in edges] values = [i[1] for i in expanded_edges] # Keep results in a local Python set, as we want to bundle as many requests as possible todo = set() for i, edge in enumerate(values): if b['id'] == edge: todo.add(i) outgoings = yield [("RO", [edges[i]]) for i in todo] values = yield [("RE", [outgoing[0]]) for outgoing in outgoings] edges = yield [("CE", [result, result]) for value in values] yield [("CE", [edge, value[1]]) for edge, value in zip(edges, values)] yield [("RETURN", [{'id': result}])] def reverseKeyLookupMultiValue(a, b, **remainder): if "value" not in b: b['value'], = yield [("RV", [b['id']])] edges, result = yield [("RO", [a['id']]), ("CN", [])] expanded_edges = yield [("RE", [i]) for i in edges] values = yield [("RV", [i[1]]) for i in expanded_edges] # Keep results in a local Python set, as we want to bundle as many requests as possible todo = set() for i, edge in enumerate(values): if b['value'] == edge: todo.add(i) outgoings = yield [("RO", [edges[i]]) for i in todo] values = yield [("RE", [outgoing[0]]) for outgoing in outgoings] edges = yield [("CE", [result, result]) for value in values] yield [("CE", [edge, value[1]]) for edge, value in zip(edges, values)] yield [("RETURN", [{'id': result}])] def reverseKeyLookup(a, b, **remainder): edges_out, edges_in = yield [("RO", [a['id']]), ("RI", [b['id']])] if edges_out is None or edges_in is None: yield [("RETURN", [{'value': ""}])] options = set(edges_out) & set(edges_in) if options: # Select one option randomly edge = options.pop() out_edges, = yield [("RO", [edge])] # Select one option randomly out_edge = out_edges.pop() e, = yield [("RE", [out_edge])] yield [("RETURN", [{'id': e[1]}])] else: yield [("RETURN", [{'value': ""}])] def instantiated_name(a, b, **remainder): if "id" not in a: a['id'], = yield [("CNV", [a['value']])] if "value" not in b: b['value'], = yield [("RV", [b["id"]])] if b['value'] == "": yield [("RETURN", [{'value': "__" + str(a['id'])}])] else: yield [("RETURN", [b])] def set_merge(a, b, **remainder): keys, = yield [("RDK", [b['id']])] edges = yield [("CE", [a['id'], a['id']]) for key in keys] _ = yield [("CE", [edge, key]) for edge, key in zip(edges, keys)] yield [("RETURN", [a])] def has_value(a, **remainder): if "value" not in a: a['value'], = yield [("RV", [a['id']])] if a['value'] is None: yield [("RETURN", [{'value': False}])] else: yield [("RETURN", [{'value': True}])] def make_reverse_dictionary(a, **remainder): reverse, = yield [("CN", [])] key_nodes, = yield [("RDK", [a['id']])] values = yield [("RDN", [a['id'], i]) for i in key_nodes] yield [("CD", [reverse, str(v), k]) for k, v in zip(key_nodes, values)] yield [("RETURN", [{'id': reverse}])] def dict_eq(a, b, **remainder): key_nodes, = yield [("RDK", [a['id']])] key_values = yield [("RV", [i]) for i in key_nodes] values = yield [("RD", [a['id'], i]) for i in key_values] values = yield [("RV", [i]) for i in values] a_dict = dict(list(zip(key_values, values))) key_nodes, = yield [("RDK", [b['id']])] key_values = yield [("RV", [i]) for i in key_nodes] values = yield [("RD", [b['id'], i]) for i in key_values] values = yield [("RV", [i]) for i in values] b_dict = dict(list(zip(key_values, values))) yield [("RETURN", [{'value': a_dict == b_dict}])] def string_substr(a, b, c, **remainder): if "value" not in a: a['value'], = yield [("RV", [a['id']])] if "value" not in b: b['value'], = yield [("RV", [b['id']])] if "value" not in c: c['value'], = yield [("RV", [c['id']])] try: new_value = a['value'][b['value']:c['value']] except: new_value = "" yield [("RETURN", [{'value': new_value}])] def integer_gt(a, b, **remainder): if 'value' not in a: a['value'], = yield [("RV", [a['id']])] if 'value' not in b: b['value'], = yield [("RV", [b['id']])] yield [("RETURN", [{'value': a['value'] > b['value']}])] def integer_neg(a, **remainder): if 'value' not in a: a['value'], = yield [("RV", [a['id']])] yield [("RETURN", [{'value': -a['value']}])] def float_gt(a, b, **remainder): if 'value' not in a: a['value'], = yield [("RV", [a['id']])] if 'value' not in b: b['value'], = yield [("RV", [b['id']])] yield [("RETURN", [{'value': a['value'] > b['value']}])] def float_neg(a, **remainder): if 'value' not in a: a['value'], = yield [("RV", [a['id']])] yield [("RETURN", [{'value': -a['value']}])] def value_neq(a, b, **remainder): if 'value' not in a: a['value'], = yield [("RV", [a['id']])] if 'value' not in b: b['value'], = yield [("RV", [b['id']])] yield [("RETURN", [{'value': a['value'] != b['value']}])] def element_neq(a, b, **remainder): if 'id' not in a or 'id' not in b: yield [("RETURN", [{'value': False}])] else: yield [("RETURN", [{'value': a['id'] != b['id']}])] def list_append(a, b, **remainder): if "id" not in b: b['id'], = yield [("CNV", [b['value']])] a_outgoing, = yield [("RO", [a['id']])] _ = yield [("CD", [a['id'], len(a_outgoing), b['id']])] yield [("RETURN", [a])] def list_read(a, b, **remainder): if 'value' not in b: b['value'], = yield [("RV", [b['id']])] result, = yield [("RD", [a['id'], b['value']])] if result is None: raise Exception("List read out of bounds: %s" % b['value']) yield [("RETURN", [{'id': result}])] def list_len(a, **remainder): outgoings, = yield [("RO", [a['id']])] result, = yield [("CNV", [len(outgoings)])] yield [("RETURN", [{'id': result}])] def dict_add(a, b, c, **remainder): if 'id' not in b: b['id'], = yield [("CNV", [b['value']])] if 'id' not in c: c['id'], = yield [("CNV", [c['value']])] new_edge, = yield [("CE", [a['id'], c['id']])] yield [("CE", [new_edge, b['id']])] yield [("RETURN", [a])] def dict_len(a, **remainder): outgoings, = yield [("RO", [a['id']])] yield [("RETURN", [{'value': len(outgoings)}])] def set_add(a, b, **remainder): if 'value' not in b: b['value'], = yield [("RV", [b['id']])] is_in, = yield [("RD", [a['id'], b['value']])] if not is_in: _, = yield [("CD", [a['id'], b['value'], a['id']])] yield [("RETURN", [a])] def set_add_node(a, b, **remainder): if 'id' not in b: b['id'], = yield [("CNV", [b['value']])] is_in, = yield [("RDN", [a['id'], b['id']])] if not is_in: edge, = yield [("CE", [a['id'], a['id']])] _, = yield [("CE", [edge, b['id']])] yield [("RETURN", [a])] def set_pop(a, **remainder): outgoing, = yield [("RO", [a['id']])] if outgoing: outgoing = outgoing[0] new_outgoing, = yield [("RO", [outgoing])] new_outgoing = new_outgoing[0] edge, _ = yield [("RE", [new_outgoing]), ("DE", [outgoing])] yield [("RETURN", [{'id': edge[1]}])] else: raise Exception("POP from empty set") yield [("RETURN", [{'id': remainder["root"]}])] def set_create(**remainder): result, = yield [("CN", [])] yield [("RETURN", [{'id': result}])] def list_create(**remainder): result, = yield [("CN", [])] yield [("RETURN", [{'id': result}])] def dict_create(**remainder): result, = yield [("CN", [])] yield [("RETURN", [{'id': result}])] def create_tuple(a, b, **remainder): if "id" not in a: a['id'], = yield [("CNV", [a['value']])] if "id" not in b: b['id'], = yield [("CNV", [b['value']])] result, = yield [("CN", [])] _, _ = yield [("CD", [result, 0, a['id']]), ("CD", [result, 1, b['id']]), ] yield [("RETURN", [{'id': result}])] def set_overlap(a, b, **remainder): a_keys, b_keys, res = yield [("RDK", [a['id']]), ("RDK", [b['id']]), ("CN", [])] a_values = yield [("RV", [i]) for i in a_keys] b_values = yield [("RV", [i]) for i in b_keys] result = set(a_values) & set(b_values) yield [("CD", [res, value, res]) for value in result] yield [("RETURN", [{'id': res}])] def list_pop_final(a, **remainder): lst, = yield [("RO", [a['id']])] length = len(lst) result, result_edge = yield [("RD", [a['id'], length - 1]), ("RDE", [a['id'], length -1])] _, = yield [("DE", [result_edge])] yield [("RETURN", [{'id': result}])] def instantiate_node(a, b, c, **remainder): if "value" not in c: c['value'], = yield [("RV", [c['id']])] if "id" not in b: b['id'], = yield [("CNV", [b['value']])] node, dict_entry, typing = \ yield [("CN", []), ("RD", [a['id'], "model"]), ("RD", [a['id'], "type_mapping"]), ] if c['value'] == "": name = "__" + str(node) name_node = {'value': name} else: name = c['value'] name_node = c yield [("CD", [dict_entry, name, node])] yield [("CD", [typing, name, b['id']])] yield [("RETURN", [name_node])] def list_insert(a, b, c, **remainder): if "id" not in b: b["id"], = yield [("CNV", [b['value']])] if "value" not in c: c['value'], = yield [("RV", [c['id']])] a_outgoing, = yield [("RO", [a['id']])] links = yield [("RD", [a['id'], i]) for i in range(c['value'], len(a_outgoing))] + \ [("RDE", [a['id'], i]) for i in range(c['value'], len(a_outgoing))] values = links[:len(links) // 2] edges = links[len(links) // 2:] yield [("CD", [a['id'], c['value'], b['id']])] + \ [("CD", [a['id'], c['value'] + 1 + index, value]) for index, value in enumerate(values)] + \ [("DE", [i]) for i in edges] yield [("RETURN", [a])] def list_delete(a, b, **remainder): if "value" not in b: b['value'], = yield [("RV", [b['id']])] a_outgoing, = yield [("RO", [a['id']])] links = yield [("RD", [a['id'], i]) for i in range(b['value'], len(a_outgoing))] + \ [("RDE", [a['id'], i]) for i in range(b['value'], len(a_outgoing))] values = links[:len(links) // 2] edges = links[len(links) // 2:] yield [("CD", [a['id'], b['value'] + index, value]) for index, value in enumerate(values[1:])] + \ [("DE", [i]) for i in edges] yield [("RETURN", [a])] def set_len(a, **remainder): if "id" not in a: yield [("RETURN", [{'value': 0}])] else: outgoing, = yield [("RO", [a['id']])] yield [("RETURN", [{'value': len(outgoing)}])] def set_in(a, b, **remainder): if "value" not in b: b['value'], = yield [("RV", [b['id']])] value, = yield [("RD", [a['id'], b['value']])] yield [("RETURN", [{'value': value is not None}])] def set_in_node(a, b, **remainder): if "id" not in b: # Not even allocated the node, so it is certain not to be in the dictionary yield [("RETURN", [{'value': False}])] value, = yield [("RDN", [a['id'], b['id']])] yield [("RETURN", [{'value': value is not None}])] def read_type(a, b, **remainder): if "value" not in b: b['value'], = yield [("RV", [b['id']])] model, type_mapping, metamodel = yield [("RD", [a['id'], 'model']), ("RD", [a['id'], 'type_mapping']), ("RD", [a['id'], 'metamodel'])] metamodel, in_model, type_value = yield [("RD", [metamodel, 'model']), ("RD", [model, b['value']]), ("RD", [type_mapping, b['value']])] if in_model is None: yield [("RETURN", [{'value': ""}])] elif type_value is None: yield [("RETURN", [{'value': ""}])] else: type_value, = yield [("RV", [type_value])] in_metamodel, = yield [("RD", [metamodel, type_value])] if in_metamodel is None: yield [("RETURN", [{'value': ""}])] else: yield [("RETURN", [{'value': type_value}])]