فهرست منبع

fix bug in matcher

Joeri Exelmans 1 سال پیش
والد
کامیت
fd91372759
1فایلهای تغییر یافته به همراه9 افزوده شده و 50 حذف شده
  1. 9 50
      transformation/matcher.py

+ 9 - 50
transformation/matcher.py

@@ -87,23 +87,11 @@ def model_to_graph(state: State, model: UUID, metamodel: UUID,
 
 
         mvs_edges = []
         mvs_edges = []
         modelrefs = {}
         modelrefs = {}
-        # constraints = {}
-
         names = {}
         names = {}
 
 
         def to_vtx(el, name):
         def to_vtx(el, name):
             # print("name:", name)
             # print("name:", name)
             if bottom.is_edge(el):
             if bottom.is_edge(el):
-                # if filter_constraint:
-                #     try:
-                #         supposed_obj = bottom.read_edge_source(el)
-                #         slot_node = od.get_slot(supposed_obj, "constraint")
-                #         if el == slot_node:
-                #             # `el` is the constraint-slot
-                #             constraints[supposed_obj] = el
-                #             return
-                #     except:
-                #         pass
                 mvs_edges.append(el)
                 mvs_edges.append(el)
                 edge = MVSEdge(el, name)
                 edge = MVSEdge(el, name)
                 names[name] = edge
                 names[name] = edge
@@ -138,57 +126,25 @@ def model_to_graph(state: State, model: UUID, metamodel: UUID,
                     tgt=uuid_to_vtx[mvs_tgt],
                     tgt=uuid_to_vtx[mvs_tgt],
                     label="tgt"))
                     label="tgt"))
 
 
-
         for node, (ref_m, name) in modelrefs.items():
         for node, (ref_m, name) in modelrefs.items():
             vtx = uuid_to_vtx[node]
             vtx = uuid_to_vtx[node]
-
             # Get MM of ref'ed model
             # Get MM of ref'ed model
             ref_mm, = bottom.read_outgoing_elements(node, "Morphism")
             ref_mm, = bottom.read_outgoing_elements(node, "Morphism")
-            # print("modelref type node:", type_node)
-
-            # Recursively convert ref'ed model to graph
-            # ref_graph = model_to_graph(state, ref_m, ref_mm, prefix=name+'/')
-
             vtx.modelref = (ref_m, ref_mm)
             vtx.modelref = (ref_m, ref_mm)
 
 
-            # We no longer flatten:
-
-            # # Flatten and create link to ref'ed model
-            # graph.vtxs += ref_model.vtxs
-            # graph.edges += ref_model.edges
-            # graph.edges.append(Edge(
-            #     src=uuid_to_vtx[node],
-            #     tgt=ref_model.vtxs[0], # which node to link to?? dirty
-            #     label="modelref"))
-
         def add_types(node):
         def add_types(node):
             vtx = uuid_to_vtx[node]
             vtx = uuid_to_vtx[node]
             type_node, = bottom.read_outgoing_elements(node, "Morphism")
             type_node, = bottom.read_outgoing_elements(node, "Morphism")
-
             # Put the type straight into the Vertex-object
             # Put the type straight into the Vertex-object
             # The benefit is that our Vertex-matching callback can then be coded cleverly, look at the types first, resulting in better performance
             # The benefit is that our Vertex-matching callback can then be coded cleverly, look at the types first, resulting in better performance
             vtx.typ = type_node
             vtx.typ = type_node
 
 
-            # The old approach (creating special vertices containing the types), commented out:
-
-            # print('node', node, 'has type', type_node)
-            # We create a Vertex storing the type
-            # type_vertex = Vertex(value=IS_TYPE(type_node))
-            # graph.vtxs.append(type_vertex)
-            # type_edge = Edge(
-            #     src=uuid_to_vtx[node],
-            #     tgt=type_vertex,
-            #     label="type")
-            # # print(type_edge)
-            # graph.edges.append(type_edge)
-
         # Add typing information for:
         # Add typing information for:
         #   - classes
         #   - classes
         #   - attributes
         #   - attributes
         #   - associations
         #   - associations
         for class_name, class_node in scd_mm.get_classes().items():
         for class_name, class_node in scd_mm.get_classes().items():
             objects = scd.get_typed_by(class_node)
             objects = scd.get_typed_by(class_node)
-            # print("typed by:", class_name, objects)
             for obj_name, obj_node in objects.items():
             for obj_name, obj_node in objects.items():
                 if _filter(obj_node):
                 if _filter(obj_node):
                     add_types(obj_node)
                     add_types(obj_node)
@@ -199,7 +155,6 @@ def model_to_graph(state: State, model: UUID, metamodel: UUID,
                         add_types(slot_node)
                         add_types(slot_node)
         for assoc_name, assoc_node in scd_mm.get_associations().items():
         for assoc_name, assoc_node in scd_mm.get_associations().items():
             objects = scd.get_typed_by(assoc_node)
             objects = scd.get_typed_by(assoc_node)
-            # print("typed by:", assoc_name, objects)
             for link_name, link_node in objects.items():
             for link_name, link_node in objects.items():
                 if _filter(link_node):
                 if _filter(link_node):
                     add_types(link_node)
                     add_types(link_node)
@@ -248,10 +203,12 @@ def match_od(state, host_m, host_mm, pattern_m, pattern_mm, pivot={}):
             except KeyError:
             except KeyError:
                 return False
                 return False
 
 
-            return cdapi.is_subtype(
+            types_ok = cdapi.is_subtype(
                 super_type_name=guest_type_name_unramified,
                 super_type_name=guest_type_name_unramified,
                 sub_type_name=host_type_name)
                 sub_type_name=host_type_name)
 
 
+            return types_ok
+
         # Memoizing the result of comparison gives a huge performance boost!
         # Memoizing the result of comparison gives a huge performance boost!
         # Especially `is_subtype_of` is very slow, and will be performed many times over on the same pair of nodes during the matching process.
         # Especially `is_subtype_of` is very slow, and will be performed many times over on the same pair of nodes during the matching process.
         # Assuming the model is not altered *during* matching, this is safe.
         # Assuming the model is not altered *during* matching, this is safe.
@@ -262,7 +219,8 @@ def match_od(state, host_m, host_mm, pattern_m, pattern_mm, pivot={}):
                 if not hasattr(h_vtx, 'typ'):
                 if not hasattr(h_vtx, 'typ'):
                     # if guest has a type, host must have a type
                     # if guest has a type, host must have a type
                     return False
                     return False
-                return self.match_types(g_vtx.typ, h_vtx.typ)
+                if not self.match_types(g_vtx.typ, h_vtx.typ):
+                    return False
 
 
             if hasattr(g_vtx, 'modelref'):
             if hasattr(g_vtx, 'modelref'):
                 if not hasattr(h_vtx, 'modelref'):
                 if not hasattr(h_vtx, 'modelref'):
@@ -271,7 +229,9 @@ def match_od(state, host_m, host_mm, pattern_m, pattern_mm, pivot={}):
                 python_code = services_od.read_primitive_value(self.bottom, g_vtx.node_id, pattern_mm)[0]
                 python_code = services_od.read_primitive_value(self.bottom, g_vtx.node_id, pattern_mm)[0]
 
 
                 try:
                 try:
-                    # Try to execute code, but if the `matched` API-function is called, we fail.
+                    # Try to execute code, but the likelyhood of failing is high:
+                    #   - the `matched` API function is not yet available
+                    #   - incompatible slots may be matched (it is only when their AttributeLinks are matched, that we know the types will be compatible)
                     with Timer(f'EVAL condition {g_vtx.name}'):
                     with Timer(f'EVAL condition {g_vtx.name}'):
                         ok = exec_then_eval(python_code,
                         ok = exec_then_eval(python_code,
                             _globals={
                             _globals={
@@ -281,8 +241,7 @@ def match_od(state, host_m, host_mm, pattern_m, pattern_mm, pivot={}):
                             _locals={'this': h_vtx.node_id})
                             _locals={'this': h_vtx.node_id})
                     self.conditions_to_check.pop(g_vtx.name, None)
                     self.conditions_to_check.pop(g_vtx.name, None)
                     return ok
                     return ok
-                except _No_Matched:
-                    # The code made a call to the `matched`-function.
+                except:
                     self.conditions_to_check[g_vtx.name] = python_code
                     self.conditions_to_check[g_vtx.name] = python_code
                     return True # to be determined later, if it's actually a match
                     return True # to be determined later, if it's actually a match