Browse Source

Compiled version of read_attribute (slow?)

Yentl Van Tendeloo 7 years ago
parent
commit
e8619ad53c
1 changed files with 63 additions and 0 deletions
  1. 63 0
      kernel/modelverse_kernel/compiled.py

+ 63 - 0
kernel/modelverse_kernel/compiled.py

@@ -509,3 +509,66 @@ def dict_copy(a, **remainder):
     keys = yield [("RV", [i]) for i in keys]
     yield [("CD", [new, k, v]) for k, v in zip(keys, values)]
     yield [("RETURN", [{'id': new}])]
+
+def read_attribute(a, b, c, root, **remainder):
+    if "value" not in b:
+        b["value"], = yield [("RV", [b['id']])]
+    if "value" not in c:
+        c["value"], = yield [("RV", [c['id']])]
+
+    m, metamodel = yield [("RD", [a['id'], "model"]), ("RD", [a['id'], "metamodel"])]
+    mm, elem, tm = yield [("RD", [metamodel, "model"]), ("RD", [m, b['value']]), ("RD", [a['id'], "type_mapping"])]
+
+    if elem is not None:
+        # Read all outgoing links and their names
+        outgoing_edges, tm = yield [("RO", [elem]), ("RD", [tm, "root"])]
+
+        if outgoing_edges:
+            outgoing_names = []
+            backlinks = {}
+            edges_out, = yield [("RO", [m])]
+            edges_out = set(edges_out)
+            for i in outgoing_edges:
+                edges_in, = yield [("RI", [i])]
+
+                if edges_in is None:
+                    continue
+
+                for edge in edges_in:
+                    if edge in edges_out:
+                        out_edges, = yield [("RO", [edge])]
+                        # Select one option randomly
+                        if out_edges:
+                            out_edge = out_edges.pop()
+                            e, = yield [("RE", [out_edge])]
+                            val, = yield [("RV", [e[1]])]
+                            backlinks[val] = i
+                            outgoing_names.append(val)
+
+            if outgoing_names:
+                # Read out the types and flatten
+                types = yield [("RD", [tm, i]) for i in outgoing_names]
+                types = yield [("RV", [i]) for i in types]
+                edges = yield [("RD", [mm, i]) for i in types]
+                sources = yield [("RE", [i]) for i in edges]
+                sources = {i[0] for i in sources}
+                backlinks = {e: backlinks[s] for e, s in zip(edges, outgoing_names)}
+
+                # List the outgoing links with the attribute in it
+                vals = yield [("RDE", [i, c['value']]) for i in sources]
+                vals = [v for v in vals if v is not None]
+
+                if vals:
+                    # Found the link and stored in vals[0]
+                    edge = vals[0]
+
+                    # Get the instance of this link
+                    if edge in backlinks:
+                        val, = yield [("RE", [backlinks[edge]])]
+                        yield [("RETURN", [{'id': val[1]}])]
+                else:
+                    outgoing_edges, = yield [("RO", [elem])]
+                    ee = yield [("RE", [i]) for i in outgoing_edges]
+                    vals = yield [("RV", [i[1]]) for i in ee]
+
+    yield [("RETURN", [{'id': root}])]