瀏覽代碼

Allow the Modelverse to process precompiled functions instead of the explicit one, if such a function is present

Yentl Van Tendeloo 9 年之前
父節點
當前提交
d26b213e74

+ 0 - 1
bootstrap/bootstrap.py

@@ -67,7 +67,6 @@ def bootstrap():
                     "dict_in": ["Boolean", "Element", "Element"],
                     "dict_in_node": ["Boolean", "Element", "Element"],
                     "dict_keys": ["Element", "Element"],
-                    "dict_reverse": ["Element", "Element", "Element"],
                     "set_add": ["Element", "Element", "Element"],
                     "set_pop": ["Element", "Element"],
                     "set_remove": ["Element", "Element", "Element"],

+ 17 - 16
bootstrap/conformance_scd.alc

@@ -92,22 +92,23 @@ String function conformance_scd(model : Element):
 		while (0 < list_len(keys)):
 			key = set_pop(keys)
 			tmp_dict = create_node()
-			slc = read_attribute(metamodel, key, "source_lower_cardinality")
-			suc = read_attribute(metamodel, key, "source_upper_cardinality")
-			tlc = read_attribute(metamodel, key, "target_lower_cardinality")
-			tuc = read_attribute(metamodel, key, "target_upper_cardinality")
-
-			if (element_neq(slc, read_root())):
-				dict_add(tmp_dict, "slc", slc)
-			if (element_neq(suc, read_root())):
-				dict_add(tmp_dict, "suc", suc)
-			if (element_neq(tlc, read_root())):
-				dict_add(tmp_dict, "tlc", tlc)
-			if (element_neq(tuc, read_root())):
-				dict_add(tmp_dict, "tuc", tuc)
-
-			if (list_len(tmp_dict) > 0):
-				dict_add(cardinalities, key, tmp_dict)
+			if (is_edge(model["model"][key])):
+				slc = read_attribute(metamodel, key, "source_lower_cardinality")
+				suc = read_attribute(metamodel, key, "source_upper_cardinality")
+				tlc = read_attribute(metamodel, key, "target_lower_cardinality")
+				tuc = read_attribute(metamodel, key, "target_upper_cardinality")
+
+				if (element_neq(slc, read_root())):
+					dict_add(tmp_dict, "slc", slc)
+				if (element_neq(suc, read_root())):
+					dict_add(tmp_dict, "suc", suc)
+				if (element_neq(tlc, read_root())):
+					dict_add(tmp_dict, "tlc", tlc)
+				if (element_neq(tuc, read_root())):
+					dict_add(tmp_dict, "tuc", tuc)
+
+				if (list_len(tmp_dict) > 0):
+					dict_add(cardinalities, key, tmp_dict)
 
 		// Iterate over each element of the model, finding out whether everything is fine
 		keys = dict_keys(model["model"])

+ 0 - 3
bootstrap/object_operations.alc

@@ -155,9 +155,6 @@ Element function getInstantiatableAttributes(model : Element, element : String):
 
 // TODO Utility functions!
 String function reverseKeyLookup(dict : Element, element : Element):
-	return dict_reverse(dict, element)
-
-	// TODO this code makes everything very inefficient; wait to enable this for once the compilation is implemented
 	Element elements
 	String name
 

+ 0 - 1
bootstrap/primitives.alc

@@ -78,7 +78,6 @@ Boolean function is_physical_float(a: Element) = ?primitives/is_physical_float
 Boolean function is_physical_string(a: Element) = ?primitives/is_physical_string
 Boolean function is_physical_boolean(a: Element) = ?primitives/is_physical_boolean
 Boolean function is_physical_action(a: Element) = ?primitives/is_physical_action
-Element function dict_reverse(a: Element, b: Element) = ?primitives/dict_reverse
 
 Element function exec(first_instr : Element):
 	// This does very ugly things, so beware!

+ 3 - 0
interface/HUTN/hutn_compiler/primitives_visitor.py

@@ -360,6 +360,9 @@ class PrimitivesVisitor(Visitor):
                 for i in range(len(parameters)):
                     n = self.get_primitive(parameters[i])
                     self.dict(ps, string.ascii_lowercase[i], n)
+
+                    # Add the name in case we want to pre-compile in the MvK
+                    self.dict(n, "name", self.value('"%s"' % string.ascii_lowercase[i]))
             b = self.get_primitive(func_body)
             self.dict(vf, "body", b)
         else:

+ 0 - 1
interface/HUTN/includes/primitives.alh

@@ -87,6 +87,5 @@ Boolean function is_physical_string(a : Element)
 Boolean function is_physical_action(a : Element)
 Boolean function is_physical_boolean(a : Element)
 Boolean function has_value(a : Element)
-Element function dict_reverse(a : Element, b : Element)
 
 Element function exec(a : Element)

+ 14 - 0
kernel/modelverse_kernel/compiled.py

@@ -0,0 +1,14 @@
+from modelverse_kernel.primitives import PrimitiveFinished
+
+def reverseKeyLookup(a, b, **remainder):
+    edges = yield [("RO", [a])]
+    expanded_edges = yield [("RE", [i]) for i in edges]
+    for i, edge in enumerate(expanded_edges):
+        if b == edge[1]:
+            # Found our edge: edges[i]
+            outgoing = yield [("RO", [edges[i]])]
+            result = yield [("RE", [outgoing[0]])]
+            raise PrimitiveFinished(result[1])
+
+    result = yield [("CNV", ["(unknown: %s)" % b])]
+    raise PrimitiveFinished(result)

+ 28 - 8
kernel/modelverse_kernel/main.py

@@ -1,4 +1,5 @@
 import modelverse_kernel.primitives as primitive_functions
+import modelverse_kernel.compiled as compiled_functions
 import sys
 import time
 
@@ -11,6 +12,7 @@ class ModelverseKernel(object):
     def __init__(self, root):
         self.root = root
         self.primitives = {}
+        self.compiled = {}
         self.returnvalue = None
         self.success = True
         self.generators = {}
@@ -54,12 +56,11 @@ class ModelverseKernel(object):
         if phase_v == "finish":
             gen = self.helper_init(user_root)
         elif isinstance(phase_v, string_types):
-            if phase_v == "init" and inst_v is None:
-                #print("%-30s(%s)" % ("PRIMITIVE " + str(self.primitives[inst]), phase_v))
-                try:
-                    gen = self.execute_primitive(user_root, inst)
-                except:
-                    raise Exception("%s: error: IP points to undefined element and is not executable as primitive.")
+            if phase_v == "init" and inst in self.compiled:
+                #print("%-30s(%s)" % ("COMPILED " + str(self.primitives[inst]), phase_v))
+                gen = self.execute_primitive(user_root, inst)
+            elif inst_v is None:
+                raise Exception("%s: error understanding command (%s, %s)" % (self.debug_info, inst_v, phase_v))
             else:
                 #print("%-30s(%s)" % (inst_v["value"], phase_v))
                 gen = getattr(self, "%s_%s" % (inst_v["value"], phase_v))(user_root)
@@ -91,6 +92,7 @@ class ModelverseKernel(object):
         bodies =        yield [("RD", [f, "body"]) for f in signatures]
         for i in range(len(keys)):
             self.primitives[bodies[i]] = getattr(primitive_functions, function_names[i])
+        self.compiled.update(self.primitives)
 
     def execute_primitive(self, user_root, inst):
         # execute_primitive
@@ -122,7 +124,10 @@ class ModelverseKernel(object):
         try:
             # Forward the message we get to this generator
             # Sometimes it might not even be a generator, in which case this should already be in the except block (i.e., for the Read Root operation)
-            prim = self.primitives[inst](**parameters)
+            if inst not in self.primitives:
+                print("Function %s" % self.compiled[inst])
+                print("    parameters: " + str(parameters))
+            prim = self.compiled[inst](**parameters)
             inp = None
             while 1:
                 inp = yield prim.send(inp)
@@ -134,7 +139,7 @@ class ModelverseKernel(object):
             result = e.result
 
             #if result is None:
-            #    raise Exception("Primitive raised exception: value of None for operation %s with parameters %s" % (self.primitives[inst], str(parameters)))
+            #    raise Exception("Primitive raised exception: value of None for operation %s with parameters %s" % (self.compiled[inst], str(parameters)))
 
         # Clean up the current stack, as if a return happened
         old_frame =     yield [("RD", [user_frame, "prev"])]
@@ -425,6 +430,21 @@ class ModelverseKernel(object):
                                   ]
             if variable is None:
                 raise Exception("%s: not found as global: %s" % (self.debug_info, var_name))
+
+            # Resolved a global, so this is a string
+            # Potentially, this might even be a function that we have precompiled already!
+            # So check whether this is the case or not
+            compiled_function = getattr(compiled_functions, var_name, None)
+            if compiled_function is not None:
+                # We have a compiled function ready!
+                print("Using compiled version of '%s'" % var_name)
+
+                # Now we have to bind the ID to the compiled functions
+                # For this, we read out the body of the resolved data
+                compiler_val = yield [("RD", [variable, "value"])]
+                compiler_body = yield [("RD", [compiler_val, "body"])]
+                self.compiled[compiler_body] = compiled_function
+
         else:
             phase_link, returnvalue_link, new_phase = \
                             yield [("RDE", [user_frame, "phase"]),