Browse Source

Fixed PM enactment code from set to list (for double enactment of e.g., join)

Yentl Van Tendeloo 7 years ago
parent
commit
0e48e93215

+ 21 - 9
bootstrap/core_algorithm.alc

@@ -838,6 +838,8 @@ Boolean function enact_action(pm : Element, element : String, mapping : Element)
 
 
 	result = execute_operation(transformation_id, inputs, input_traceability_model)
 	result = execute_operation(transformation_id, inputs, input_traceability_model)
 
 
+	log(string_join("Finished: ", read_attribute(pm, element, "name")))
+
 	if (element_eq(result, read_root())):
 	if (element_eq(result, read_root())):
 		// Something went wrong!
 		// Something went wrong!
 		output("Failure")
 		output("Failure")
@@ -936,48 +938,55 @@ Void function enact_PM(pm : Element, mapping : Element):
 		dict_add(activity_to_task, set_pop(exec_nodes), set_create())
 		dict_add(activity_to_task, set_pop(exec_nodes), set_create())
 
 
 	// Create the worklist with the Start instance as first element
 	// Create the worklist with the Start instance as first element
-	worklist = set_create()
-	set_add(worklist, set_pop(allInstances(pm, "Start")))
+	worklist = list_create()
+	list_append(worklist, set_pop(allInstances(pm, "Start")))
 
 
 	// Keep on iterating until we reach finish
 	// Keep on iterating until we reach finish
 	while (True):
 	while (True):
 		// Check if there are PM elements to expand
 		// Check if there are PM elements to expand
-		if (set_len(worklist) > 0):
+		if (list_len(worklist) > 0):
 			// There is something we can do, so do it!
 			// There is something we can do, so do it!
-			element = set_pop(worklist)
+			element = list_pop_final(worklist)
 
 
 			// Find the type (to see what to do with it)
 			// Find the type (to see what to do with it)
 			//   this does not yet yield the type of transformation, if it is an Execution
 			//   this does not yet yield the type of transformation, if it is an Execution
 			type = read_type(pm, element)
 			type = read_type(pm, element)
+			log("Process type " + type)
 
 
 			// Some types have nothing to do, such as start and fork
 			// Some types have nothing to do, such as start and fork
 			// Therefore, they are not mentioned in the following conditional
 			// Therefore, they are not mentioned in the following conditional
 
 
 			if (type == "Finish"):
 			if (type == "Finish"):
 				// We have finished, so terminate
 				// We have finished, so terminate
+				log("Finish")
 				break!
 				break!
 			elif (type == "Join"):
 			elif (type == "Join"):
 				// Only do this if all dependencies are fullfilled
 				// Only do this if all dependencies are fullfilled
 				// So add to the counter of this Join
 				// So add to the counter of this Join
+				log("Join")
 				dict_overwrite(counters, element, integer_addition(counters[element], 1))
 				dict_overwrite(counters, element, integer_addition(counters[element], 1))
 
 
 				// Now check whether we have enough tokens to execute the Join itself
 				// Now check whether we have enough tokens to execute the Join itself
 				Integer required
 				Integer required
 				Integer got
 				Integer got
-				required = set_len(allIncomingAssociationInstances(pm, element, "Next")) + set_len(allIncomingAssociationInstances(pm, element, "Else"))
+				required = set_len(allIncomingAssociationInstances(pm, element, "Next")) + set_len(allIncomingAssociationInstances(pm, element, "Else")) + set_len(allIncomingAssociationInstances(pm, element, "Then"))
 				got = counters[element]
 				got = counters[element]
 				if (got == required):
 				if (got == required):
 					// Reset counter to 0
 					// Reset counter to 0
 					dict_overwrite(counters, element, 0)
 					dict_overwrite(counters, element, 0)
+					log("Got all!")
 
 
 					// And continue
 					// And continue
 				else:
 				else:
 					// We haven't gotten all yet, so we wait (i.e., continue without adding Next link to worklist)
 					// We haven't gotten all yet, so we wait (i.e., continue without adding Next link to worklist)
+					log("Insufficient: " + cast_value(got))
+					log("Required: " + cast_value(required))
 					continue!
 					continue!
 
 
 			elif (type == "Exec"):
 			elif (type == "Exec"):
 				// Execute a transformation
 				// Execute a transformation
 				// This the difficult part!
 				// This the difficult part!
+				log("Exec")
 
 
 				Element args
 				Element args
 				String taskname
 				String taskname
@@ -998,7 +1007,7 @@ Void function enact_PM(pm : Element, mapping : Element):
 			String next
 			String next
 			while (set_len(all_next) > 0):
 			while (set_len(all_next) > 0):
 				next = set_pop(all_next)
 				next = set_pop(all_next)
-				set_add(worklist, next)
+				list_append(worklist, next)
 		else:
 		else:
 			// No new tasks to spawn, so go and check on all running activities
 			// No new tasks to spawn, so go and check on all running activities
 			if (dict_len(task_to_result) > 0):
 			if (dict_len(task_to_result) > 0):
@@ -1009,6 +1018,7 @@ Void function enact_PM(pm : Element, mapping : Element):
 				keys = dict_keys(task_to_result)
 				keys = dict_keys(task_to_result)
 				while (set_len(keys) > 0):
 				while (set_len(keys) > 0):
 					task = set_pop(keys)
 					task = set_pop(keys)
+					log("Detected finished " + cast_value(task_to_activity[task]))
 					result = task_to_result[task]
 					result = task_to_result[task]
 
 
 					Element all_next
 					Element all_next
@@ -1016,22 +1026,24 @@ Void function enact_PM(pm : Element, mapping : Element):
 					String next
 					String next
 					while (set_len(all_next) > 0):
 					while (set_len(all_next) > 0):
 						next = set_pop(all_next)
 						next = set_pop(all_next)
+						log("Next: " + cast_value(next))
 
 
 						if (read_type(pm, next) == "Decision"):
 						if (read_type(pm, next) == "Decision"):
 							// Got decision node, so expand immediately
 							// Got decision node, so expand immediately
 							if (result):
 							if (result):
-								set_add(worklist, set_pop(allAssociationDestinations(pm, next, "Then")))
+								list_append(worklist, set_pop(allAssociationDestinations(pm, next, "Then")))
 							else:
 							else:
-								set_add(worklist, set_pop(allAssociationDestinations(pm, next, "Else")))
+								list_append(worklist, set_pop(allAssociationDestinations(pm, next, "Else")))
 						else:
 						else:
 							// Other node, so just append for further processing
 							// Other node, so just append for further processing
-							set_add(worklist, next)
+							list_append(worklist, next)
 
 
 					set_remove(activity_to_task[task_to_activity[task]], task)
 					set_remove(activity_to_task[task_to_activity[task]], task)
 					dict_delete(task_to_result, task)
 					dict_delete(task_to_result, task)
 					dict_delete(task_to_activity, task)
 					dict_delete(task_to_activity, task)
 			else:
 			else:
 				// No finished activities either, so we sleep for some time
 				// No finished activities either, so we sleep for some time
+				log("No finished activities...")
 				sleep(0.1)
 				sleep(0.1)
 
 
 	// Remove all mock locations again
 	// Remove all mock locations again

+ 2 - 0
hybrid_server/classes/mvkcontroller.xml

@@ -298,6 +298,7 @@
                     </state>
                     </state>
                 </state>
                 </state>
 
 
+                <!--
                 <state id="mvs_GC" initial="suspend_tasks">
                 <state id="mvs_GC" initial="suspend_tasks">
                     <state id="suspend_tasks">
                     <state id="suspend_tasks">
                         <onentry>
                         <onentry>
@@ -317,6 +318,7 @@
                         <transition after="self.sccd_yield() + 10" target="."/>
                         <transition after="self.sccd_yield() + 10" target="."/>
                     </state>
                     </state>
                 </state>
                 </state>
+                -->
             </parallel>
             </parallel>
 
 
             <state id="remove_sockets">
             <state id="remove_sockets">

+ 1 - 0
hybrid_server/classes/socket.xml

@@ -146,6 +146,7 @@
             </state>
             </state>
             <transition event="close" target="../close"/>
             <transition event="close" target="../close"/>
         </parallel>
         </parallel>
+
         <state id="close">
         <state id="close">
             <onentry>
             <onentry>
                 <raise port="socket_out" event="close_socket">
                 <raise port="socket_out" event="close_socket">

+ 28 - 24
kernel/modelverse_kernel/main.py

@@ -201,7 +201,8 @@ class ModelverseKernel(object):
                    "  " * (nested_indent + 2) + "yield [('CD', [_root, 'input', nxt])]\n" + \
                    "  " * (nested_indent + 2) + "yield [('CD', [_root, 'input', nxt])]\n" + \
                    "  " * (nested_indent + 2) + "_result = val\n" + \
                    "  " * (nested_indent + 2) + "_result = val\n" + \
                    "  " * (nested_indent + 2) + "break\n" + \
                    "  " * (nested_indent + 2) + "break\n" + \
-                   "  " * (nested_indent + 1)+ "else:\n" + \
+                   "  " * (nested_indent + 1) + "else:\n" + \
+                   "  " * (nested_indent + 2) + "print('WAIT FOR INPUT...')\n" + \
                    "  " * (nested_indent + 2) + "yield None\n"
                    "  " * (nested_indent + 2) + "yield None\n"
             instruction = "_result"
             instruction = "_result"
 
 
@@ -217,15 +218,18 @@ class ModelverseKernel(object):
                           "  " * indent + "yield [('DE', [_outputs_e])]\n" + \
                           "  " * indent + "yield [('DE', [_outputs_e])]\n" + \
                           "  " * indent + "yield [('CD', [_root, 'last_output', _new])]\n"
                           "  " * indent + "yield [('CD', [_root, 'last_output', _new])]\n"
 
 
-
         elif inst_type["value"] == "resolve":
         elif inst_type["value"] == "resolve":
             value, = yield [("RD", [inst, "var"])]
             value, = yield [("RD", [inst, "var"])]
             str_value, = yield [("RV", [value])]
             str_value, = yield [("RV", [value])]
             if str_value:
             if str_value:
                 # Is a global
                 # Is a global
                 prev = \
                 prev = \
-                       "  " * nested_indent + "%s, = yield [('RD', [_globs, '%s'])]\n" % (str_value, str_value) + \
-                       "  " * nested_indent + "%s, = yield [('RD', [%s, 'value'])]\n" % (str_value, str_value)
+                       "  " * nested_indent + "if '%s' not in _cache:\n" % str_value + \
+                       "  " * (nested_indent + 1) + "%s, = yield [('RD', [_globs, '%s'])]\n" % (str_value, str_value) + \
+                       "  " * (nested_indent + 1) + "%s, = yield [('RD', [%s, 'value'])]\n" % (str_value, str_value) + \
+                       "  " * (nested_indent + 1) + "_cache['%s'] = %s\n" % (str_value, str_value) + \
+                       "  " * nested_indent + "else:\n" + \
+                       "  " * (nested_indent + 1) + "%s = _cache['%s']\n" % (str_value, str_value)
                 instruction = str_value
                 instruction = str_value
 
 
                 if self.jit.get_global_body_id(str_value) is None:
                 if self.jit.get_global_body_id(str_value) is None:
@@ -235,7 +239,6 @@ class ModelverseKernel(object):
                     val, = yield [("RD", [val, 'value'])]
                     val, = yield [("RD", [val, 'value'])]
                     val, = yield [("RD", [val, 'body'])]
                     val, = yield [("RD", [val, 'body'])]
 
 
-                    print("Registering global " + str(str_value) + " using " + str(val))
                     self.jit.register_global(val, str_value)
                     self.jit.register_global(val, str_value)
             else:
             else:
                 # Is a local
                 # Is a local
@@ -280,24 +283,24 @@ class ModelverseKernel(object):
                 computation += prev_res
                 computation += prev_res
                 param_list[name] = instruction_res
                 param_list[name] = instruction_res
 
 
+            value = "func_result_" + str(ModelverseKernel.counter)
+            ModelverseKernel.counter += 1
+
             if func_name in intrinsics:
             if func_name in intrinsics:
-                #instruction = "  " * indent + intrinsics[func_name](*param_list)
-                # TODO
-                pass
+                #TODO test and fix
+                actual_computation = value + " = " + intrinsics[func_name](*param_list)
             else:
             else:
-                value = "func_result_" + str(ModelverseKernel.counter)
-                ModelverseKernel.counter += 1
                 param_list = "{" + ", ".join(["'%s': %s" % (k, v) for k, v in param_list.items()]) + "}"
                 param_list = "{" + ", ".join(["'%s': %s" % (k, v) for k, v in param_list.items()]) + "}"
                 actual_computation = "%s, = yield [('CALL_ARGS', [_mvk.execute_jit_internal, (_root, %s, _taskname, %s)])]\n" % (value, func_name, param_list)
                 actual_computation = "%s, = yield [('CALL_ARGS', [_mvk.execute_jit_internal, (_root, %s, _taskname, %s)])]\n" % (value, func_name, param_list)
 
 
-                if indent == 0:
-                    # No indent, meaning that we use it inline
-                    # Therefore, we output the prev and value individually
-                    prev, instruction = prev_func_name + computation + "  " * nested_indent + actual_computation, value
-                else:
-                    # Some indentation, meaning that we don't even use the return value
-                    # Therefore, we only do the yield
-                    prev, instruction = prev_func_name + computation, "  " * indent + actual_computation
+            if indent == 0:
+                # No indent, meaning that we use it inline
+                # Therefore, we output the prev and value individually
+                prev, instruction = prev_func_name + computation + "  " * nested_indent + actual_computation, value
+            else:
+                # Some indentation, meaning that we don't even use the return value
+                # Therefore, we only do the yield
+                prev, instruction = prev_func_name + computation, "  " * indent + actual_computation
 
 
         elif inst_type["value"] == "access":
         elif inst_type["value"] == "access":
             value, = yield [("RD", [inst, "var"])]
             value, = yield [("RD", [inst, "var"])]
@@ -333,24 +336,25 @@ class ModelverseKernel(object):
             print("Ignoring mutable or unreadable: %s" % suggested_name)
             print("Ignoring mutable or unreadable: %s" % suggested_name)
             raise jit.JitCompilationFailedException("FAIL")
             raise jit.JitCompilationFailedException("FAIL")
 
 
-        print("Reading function: %s" % suggested_name)
+        #print("Reading function: %s" % suggested_name)
         (prev, printed), = yield [("CALL_ARGS", [self.print_instruction, (inst, 1)])]
         (prev, printed), = yield [("CALL_ARGS", [self.print_instruction, (inst, 1)])]
         preamble = "  _globs, = yield [('RD', [kwargs['task_root'], 'globals'])]\n" + \
         preamble = "  _globs, = yield [('RD', [kwargs['task_root'], 'globals'])]\n" + \
                    "  _root = kwargs['task_root']\n" + \
                    "  _root = kwargs['task_root']\n" + \
                    "  _taskname = kwargs['taskname']\n" + \
                    "  _taskname = kwargs['taskname']\n" + \
-                   "  _mvk = kwargs['mvk']\n"
+                   "  _mvk = kwargs['mvk']\n" + \
+                   "  _cache = {}\n"
         printed = preamble + prev + printed
         printed = preamble + prev + printed
-        print("Total printed function: ")
+        #print("Total printed function: ")
         if params:
         if params:
             func = "def " + suggested_name + "(" + ", ".join([chr(ord('a') + i) for i in range(len(params))]) + ", **kwargs):\n" + "".join(["  var_%s = %s\n" % (param, chr(ord('a') + i)) for i, param in enumerate(params)]) + printed
             func = "def " + suggested_name + "(" + ", ".join([chr(ord('a') + i) for i in range(len(params))]) + ", **kwargs):\n" + "".join(["  var_%s = %s\n" % (param, chr(ord('a') + i)) for i, param in enumerate(params)]) + printed
         else:
         else:
             func = "def " + suggested_name + "(**kwargs):\n" + printed
             func = "def " + suggested_name + "(**kwargs):\n" + printed
         
         
-        print(func)
+        #print(func)
 
 
         # To write out all generated functions
         # To write out all generated functions
-        #with open('/tmp/junk/%s' % suggested_name, 'w') as f:
-        #    f.write(func)
+        with open('/tmp/junk/%s' % suggested_name, 'w') as f:
+            f.write(func)
 
 
         raise primitive_functions.PrimitiveFinished(func)
         raise primitive_functions.PrimitiveFinished(func)
 
 

+ 1 - 0
run_pw.py

@@ -1,5 +1,6 @@
 import shutil
 import shutil
 import sys
 import sys
+import os
 sys.path.append("wrappers")
 sys.path.append("wrappers")
 from modelverse import *
 from modelverse import *
 import threading
 import threading

+ 3 - 0
scripts/run_local_modelverse.py

@@ -36,6 +36,9 @@ try:
     sys.path.append(".")
     sys.path.append(".")
     os.chdir("hybrid_server")
     os.chdir("hybrid_server")
 
 
+    import stacktracer
+    stacktracer.trace_start("trace.html",interval=5,auto=True) # Set auto flag to always update file!
+
     import server
     import server
     import sccd.runtime.socket2event as socket2event
     import sccd.runtime.socket2event as socket2event
 
 

+ 1 - 1
wrappers/modelverse_SCCD.py

@@ -1,7 +1,7 @@
 """
 """
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 Generated by Statechart compiler by Glenn De Jonghe, Joeri Exelmans, Simon Van Mierlo, and Yentl Van Tendeloo (for the inspiration)
 
 
-Date:   Tue Apr 24 14:39:15 2018
+Date:   Tue Apr 24 17:47:15 2018
 
 
 Model author: Yentl Van Tendeloo
 Model author: Yentl Van Tendeloo
 Model name:   MvK Server
 Model name:   MvK Server