|
@@ -179,3 +179,117 @@ def allInstances(a, b, **remainder):
|
|
|
v = yield [("RV", [i]) for i in final]
|
|
|
_ = yield [("CE", [result, i]) for i in final]
|
|
|
raise PrimitiveFinished(result)
|
|
|
+
|
|
|
+def add_AL(a, b, **remainder):
|
|
|
+ worklist = [(b, "funcdef")]
|
|
|
+ added = set()
|
|
|
+ type_cache = {}
|
|
|
+
|
|
|
+ model_dict = yield [("RD", [a, "model"])]
|
|
|
+ metamodel = yield [("RD", [a, "metamodel"])]
|
|
|
+ metamodel_dict = yield [("RD", [metamodel, "model"])]
|
|
|
+ type_map = yield [("RD", [a, "type_mapping"])]
|
|
|
+ outgoing = yield [("RO", [model_dict])]
|
|
|
+ edges = yield [("RE", [i]) for i in outgoing]
|
|
|
+ added |= set([i[1] for i in edges])
|
|
|
+
|
|
|
+ result = yield [("CNV", ["__%s" % b])]
|
|
|
+
|
|
|
+ # All the action language elements and their expected output links
|
|
|
+ type_links = {
|
|
|
+ "if": [("cond", ""), ("then", ""), ("else", ""), ("next", "")],
|
|
|
+ "while": [("cond", ""), ("body", ""), ("next", "")],
|
|
|
+ "assign": [("var", ""), ("value", ""), ("next", "")],
|
|
|
+ "break": [("while", "while")],
|
|
|
+ "continue": [("while", "while")],
|
|
|
+ "return": [("value", "")],
|
|
|
+ "resolve": [("var", "")],
|
|
|
+ "access": [("var", "")],
|
|
|
+ "constant": [("node", "")],
|
|
|
+ "output": [("node", ""), ("next", "")],
|
|
|
+ "global": [("var", "String"), ("next", "")],
|
|
|
+ "param": [("name", "String"), ("value", ""), ("next_param", "param")],
|
|
|
+ "funcdef": [("body", ""), ("next", "")],
|
|
|
+ "call": [("func", ""), ("params", "param"), ("last_param", "param"), ("next", "")],
|
|
|
+ }
|
|
|
+
|
|
|
+ # Already add some often used types to the type cache, so we don't have to check for their presence
|
|
|
+ to_str, string = yield [("RD", [metamodel_dict, "to_str"]),
|
|
|
+ ("RD", [metamodel_dict, "String"])]
|
|
|
+
|
|
|
+ type_cache = {"to_str": to_str,
|
|
|
+ "String": string}
|
|
|
+
|
|
|
+ while worklist:
|
|
|
+ # Fetch the element and see if we need to add it
|
|
|
+ worknode, expected_type = worklist.pop(0)
|
|
|
+ if worknode in added:
|
|
|
+ continue
|
|
|
+
|
|
|
+ # Determine type of element
|
|
|
+ if expected_type == "":
|
|
|
+ value = yield [("RV", [worknode])]
|
|
|
+ if (isinstance(value, dict)) and ("value" in value):
|
|
|
+ v = value["value"]
|
|
|
+ if v in ["if", "while", "assign", "call", "break", "continue", "return", "resolve", "access", "constant", "global", "declare"]:
|
|
|
+ expected_type = v
|
|
|
+ else:
|
|
|
+ expected_type = "Any"
|
|
|
+ else:
|
|
|
+ expected_type = "Any"
|
|
|
+
|
|
|
+ # Fill the cache
|
|
|
+ if expected_type not in type_cache:
|
|
|
+ type_cache[expected_type] = yield [("RD", [metamodel_dict, expected_type])]
|
|
|
+
|
|
|
+ # Need to add it now
|
|
|
+ yield [("CD", [model_dict, "__%s" % worknode, worknode])]
|
|
|
+ added.add(worknode)
|
|
|
+ # NOTE can't just use CD here, as the key is a node and not a value
|
|
|
+ t1 = yield [("CE", [type_map, type_cache[expected_type]])]
|
|
|
+ t2 = yield [("CE", [t1, worknode])]
|
|
|
+ if t1 is None or t2 is None:
|
|
|
+ raise Exception("ERROR")
|
|
|
+
|
|
|
+ # Now add all its outgoing links, depending on the type we actually saw
|
|
|
+ links = type_links.get(expected_type, [])
|
|
|
+ for link in links:
|
|
|
+ link_name, destination_type = link
|
|
|
+
|
|
|
+ # Check if the link actually exists
|
|
|
+ destination = yield [("RD", [worknode, link_name])]
|
|
|
+ if destination is not None:
|
|
|
+ # If so, we add it and continue
|
|
|
+ edge = yield [("RDE", [worknode, link_name])]
|
|
|
+ edge_outlinks = yield [("RO", [edge])]
|
|
|
+ edge_outlink = edge_outlinks[0]
|
|
|
+ edge_name = yield [("RE", [edge_outlink])]
|
|
|
+ edge_name = edge_name[1]
|
|
|
+ # Now add: edge, edge_outlink, edge_name
|
|
|
+
|
|
|
+ # Add 'edge'
|
|
|
+ yield [("CD", [model_dict, "__%s" % edge, edge])]
|
|
|
+ added.add(edge)
|
|
|
+ link_type = "%s_%s" % (expected_type, link_name)
|
|
|
+ if link_type not in type_cache:
|
|
|
+ type_cache[link_type] = yield [("RD", [metamodel_dict, link_type])]
|
|
|
+ t = yield [("CE", [type_map, type_cache[link_type]])]
|
|
|
+ yield [("CE", [t, edge])]
|
|
|
+
|
|
|
+ # Add 'edge_outlink'
|
|
|
+ yield [("CD", [model_dict, "__%s" % edge_outlink, edge_outlink])]
|
|
|
+ added.add(edge_outlink)
|
|
|
+ t = yield [("CE", [type_map, type_cache["to_str"]])]
|
|
|
+ yield [("CE", [t, edge_outlink])]
|
|
|
+
|
|
|
+ # Add 'edge_name' (if not present)
|
|
|
+ if edge_name not in added:
|
|
|
+ yield [("CD", [model_dict, "__%s" % edge_name, edge_name])]
|
|
|
+ t = yield [("CE", [type_map, type_cache["String"]])]
|
|
|
+ yield [("CE", [t, edge_name])]
|
|
|
+ added.add(edge_name)
|
|
|
+
|
|
|
+ # Add the destination to the worklist
|
|
|
+ worklist.append((destination, destination_type))
|
|
|
+
|
|
|
+ raise PrimitiveFinished(result)
|