فهرست منبع

Merge branch 'testing'

Yentl Van Tendeloo 7 سال پیش
والد
کامیت
1d24c1ea93
100فایلهای تغییر یافته به همراه2093 افزوده شده و 16832 حذف شده
  1. 1 0
      .gitignore
  2. 0 2
      bootstrap/bootstrap.py
  3. 1 1
      bootstrap/constructors.alc
  4. 43 9
      bootstrap/core_algorithm.alc
  5. 0 2
      bootstrap/jit.alc
  6. 11 0
      bootstrap/main.alc
  7. 1 0
      bootstrap/metamodels.alt
  8. 1 1
      bootstrap/mini_modify.alc
  9. 2 2
      bootstrap/model_management.alc
  10. 8 2
      bootstrap/object_operations.alc
  11. 0 3
      bootstrap/primitives.alc
  12. 1 0
      bootstrap/ramify.alc
  13. 37 9
      bootstrap/semi_primitives.alc
  14. 20 3
      bootstrap/transform.alc
  15. 9 4
      bootstrap/typing.alc
  16. 2 0
      bootstrap/utils.alc
  17. 116 124
      doc/actionlanguage.rst
  18. 0 8
      doc/concrete_syntax.rst
  19. 1 0
      doc/developer.rst
  20. 2 0
      doc/index.rst
  21. 6 2
      doc/interaction.rst
  22. 4 0
      doc/jit.rst
  23. 0 1
      doc/language_engineer.rst
  24. 15 1
      doc/modeller_modellanguage.rst
  25. 36 12
      doc/modelling.rst
  26. 2 2
      doc/transformations.rst
  27. 57 19
      doc/wrappers.rst
  28. 40 0
      examples/SCCD_execute.py
  29. 16 0
      examples/analyze_LoLa.py
  30. 30 0
      examples/debug_DEVS.py
  31. 43 0
      examples/live_modelling_CTCBD.py
  32. 53 0
      examples/live_modelling_DTCBD.py
  33. 48 0
      examples/live_modelling_FSA.py
  34. 27 0
      examples/pm_simulation.py
  35. 103 0
      examples/powerwindow.py
  36. 18 0
      examples/render_DTCBD_graphical.py
  37. 18 0
      examples/render_DTCBD_plot.py
  38. 10 49
      hybrid_server/classes/mvkcontroller.xml
  39. 1 0
      hybrid_server/classes/socket.xml
  40. 11 0
      hybrid_server/classes/task.xml
  41. 0 3
      hybrid_server/server.xml
  42. 102 0
      hybrid_server/stacktracer.py
  43. 0 0
      integration/code/CBD_mapper.mvc
  44. 0 0
      integration/code/MM_rendered_graphical.mvc
  45. 0 0
      integration/code/SCCD.mvc
  46. 0 0
      integration/code/SCCD_Trace.mvc
  47. 15 15
      integration/code/SCCD_all.mvc
  48. 1 0
      models/SCCD_execute.alc
  49. 60 163
      integration/test_powerwindow.py
  50. 9 13
      integration/utils.py
  51. 0 1
      interface/HUTN/hutn_compiler/model_visitor.py
  52. 0 2
      interface/HUTN/includes/jit.alh
  53. 16 1
      interface/simple_plot/main.py
  54. 0 319
      kernel/modelverse_jit/bytecode_interpreter.py
  55. 0 312
      kernel/modelverse_jit/bytecode_ir.py
  56. 0 117
      kernel/modelverse_jit/bytecode_parser.py
  57. 0 374
      kernel/modelverse_jit/bytecode_to_cfg.py
  58. 0 725
      kernel/modelverse_jit/bytecode_to_tree.py
  59. 0 98
      kernel/modelverse_jit/cfg_data_structures.py
  60. 0 113
      kernel/modelverse_jit/cfg_dominators.py
  61. 0 1209
      kernel/modelverse_jit/cfg_ir.py
  62. 0 546
      kernel/modelverse_jit/cfg_optimization.py
  63. 0 268
      kernel/modelverse_jit/cfg_ssa_construction.py
  64. 0 1021
      kernel/modelverse_jit/cfg_to_tree.py
  65. 0 500
      kernel/modelverse_jit/intrinsics.py
  66. 0 1043
      kernel/modelverse_jit/jit.py
  67. 0 16
      kernel/modelverse_jit/jit_primitives.py
  68. 0 191
      kernel/modelverse_jit/runtime.py
  69. 0 52
      kernel/modelverse_jit/source_map.py
  70. 0 1954
      kernel/modelverse_jit/tree_ir.py
  71. 208 115
      kernel/modelverse_kernel/compiled.py
  72. 0 1261
      kernel/modelverse_kernel/generated.py
  73. 190 0
      kernel/modelverse_kernel/jit.py
  74. 0 1061
      kernel/modelverse_kernel/legacy.py
  75. 411 126
      kernel/modelverse_kernel/main.py
  76. 251 219
      kernel/modelverse_kernel/primitives.py
  77. 36 369
      kernel/modelverse_kernel/request_handler.py
  78. 0 17
      kernel/mvk_server/python_runtime/.project
  79. 0 5
      kernel/mvk_server/python_runtime/.pydevproject
  80. 0 0
      kernel/mvk_server/python_runtime/__init__.py
  81. 0 9
      kernel/mvk_server/python_runtime/accurate_time.py
  82. 0 58
      kernel/mvk_server/python_runtime/event_queue.py
  83. 0 3
      kernel/mvk_server/python_runtime/infinity.py
  84. 0 1
      kernel/mvk_server/python_runtime/libs/__init__.py
  85. 0 59
      kernel/mvk_server/python_runtime/libs/drawing.py
  86. 0 111
      kernel/mvk_server/python_runtime/libs/ui.py
  87. 0 19
      kernel/mvk_server/python_runtime/libs/utils.py
  88. 0 22
      kernel/mvk_server/python_runtime/nextafter.py
  89. 0 945
      kernel/mvk_server/python_runtime/statecharts_core.py
  90. 0 21
      kernel/mvk_server/python_runtime/tkinter_eventloop.py
  91. 0 17
      kernel/mvk_server/python_sccd_compiler/.project
  92. 0 5
      kernel/mvk_server/python_sccd_compiler/.pydevproject
  93. 0 0
      kernel/mvk_server/python_sccd_compiler/__init__.py
  94. 0 14
      kernel/mvk_server/python_sccd_compiler/compiler_exceptions.py
  95. 0 911
      kernel/mvk_server/python_sccd_compiler/generic_generator.py
  96. 0 996
      kernel/mvk_server/python_sccd_compiler/generic_language_constructs.py
  97. 0 285
      kernel/mvk_server/python_sccd_compiler/javascript_writer.py
  98. 0 170
      kernel/mvk_server/python_sccd_compiler/lexer.py
  99. 0 701
      kernel/mvk_server/python_sccd_compiler/old_generators/csharp_generator.py
  100. 0 0
      kernel/mvk_server/python_sccd_compiler/old_generators/javascript_generator.py

+ 1 - 0
.gitignore

@@ -13,3 +13,4 @@ doc/al_rules/*.eps
 *.swp
 *.swo
 .tmp_*
+services/DEVS_batch/models/*.py

+ 0 - 2
bootstrap/bootstrap.py

@@ -46,8 +46,6 @@ def bootstrap():
                     "cast_integer": ["Integer", "Element"],
                     "cast_value": ["String", "Element"],
                     "cast_id": ["String", "Element"],
-                    "list_insert": ["Element", "Element", "Integer", "Element"],
-                    "list_delete": ["Element", "Element", "Integer"],
                     "dict_add_fast": ["Element", "Element", "Element", "Element"],
                     "dict_delete": ["Element", "Element", "Element"],
                     "dict_delete_node": ["Element", "Element", "Element"],

+ 1 - 1
bootstrap/constructors.alc

@@ -112,7 +112,7 @@ String function construct_global(model : Element, list : Element):
 			create_al_link(model, "resolve_var", res, instantiate_value(model, "String", "", "create_node"), "var")
 		elif (op == "const"):
 			value = instantiate_value(model, "constant", "", create_value(!constant))
-			create_al_link(model, "constant_node", value, list_pop_final(list), "node")
+			create_al_link(model, "constant_node", value, instantiate_value(model, "Element", "", list_pop_final(list)), "node")
 		create_al_link(model, "assign_value", assign, value, "value")
 
 		Element result

+ 43 - 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)
 
+	log(string_join("Finished: ", read_attribute(pm, element, "name")))
+
 	if (element_eq(result, read_root())):
 		// Something went wrong!
 		output("Failure")
@@ -936,15 +938,15 @@ Void function enact_PM(pm : Element, mapping : Element):
 		dict_add(activity_to_task, set_pop(exec_nodes), set_create())
 
 	// 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
 	while (True):
 		// 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!
-			element = set_pop(worklist)
+			element = list_pop_final(worklist)
 
 			// Find the type (to see what to do with it)
 			//   this does not yet yield the type of transformation, if it is an Execution
@@ -964,7 +966,7 @@ Void function enact_PM(pm : Element, mapping : Element):
 				// Now check whether we have enough tokens to execute the Join itself
 				Integer required
 				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]
 				if (got == required):
 					// Reset counter to 0
@@ -998,7 +1000,7 @@ Void function enact_PM(pm : Element, mapping : Element):
 			String next
 			while (set_len(all_next) > 0):
 				next = set_pop(all_next)
-				set_add(worklist, next)
+				list_append(worklist, next)
 		else:
 			// No new tasks to spawn, so go and check on all running activities
 			if (dict_len(task_to_result) > 0):
@@ -1020,12 +1022,12 @@ Void function enact_PM(pm : Element, mapping : Element):
 						if (read_type(pm, next) == "Decision"):
 							// Got decision node, so expand immediately
 							if (result):
-								set_add(worklist, set_pop(allAssociationDestinations(pm, next, "Then")))
+								list_append(worklist, set_pop(allAssociationDestinations(pm, next, "Then")))
 							else:
-								set_add(worklist, set_pop(allAssociationDestinations(pm, next, "Else")))
+								list_append(worklist, set_pop(allAssociationDestinations(pm, next, "Else")))
 						else:
 							// 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)
 					dict_delete(task_to_result, task)
@@ -1046,6 +1048,7 @@ String function cmd_help():
 	result = ""
 	result = result + ("Model operations\n")
 	result = result + ("    model_add                       -- Add a new model\n")
+	result = result + ("    model_move                      -- Move a model to a different location\n")
 	result = result + ("    model_modify                    -- Modify an existing model\n")
 	result = result + ("    model_list                      -- List all models\n")
 	result = result + ("    model_list_full                 -- List all models with full info\n")
@@ -1093,6 +1096,35 @@ String function cmd_help():
 
 	return result!
 
+String function cmd_model_move(source : String, target : String):
+	String source_id
+	source_id = get_entry_id(source)
+	if (source_id != ""):
+		if (get_entry_id(target) == ""):
+			// Create folders on path to the target
+			create_folders(current_user_id, get_foldername(target))
+
+			// Change location, first the name
+			instantiate_attribute(core, source_id, "name", target)
+
+			// Now the folder links
+			Element links
+			links = allIncomingAssociationInstances(core, source_id, "contains")
+			while (set_len(links) > 0):
+				model_delete_element(core, set_pop(links))
+			instantiate_link(core, "contains", "", get_entry_id(get_foldername(target)), source_id)
+
+			// Flush caches
+			dict_add(caches["models"], target, caches["models"][source])
+			dict_delete(caches["models"], source)
+
+			// Done
+			return "Success"!
+		else:
+			return "Model exists: " + target!
+	else:
+		return "Model does not exist: " + source!
+
 String function cmd_model_add(type : String, name : String, code : String):
 	// Model addition operation, which uses model upload commands of the compiler
 	String location
@@ -2367,6 +2399,8 @@ Void function user_function_skip_init(user_id : String):
 			output(cmd_help())
 		elif (cmd == "model_add"):
 			output(cmd_model_add(single_input("Model type?"), single_input("Model name?"), single_input("Model textual representation?")))
+		elif (cmd == "model_move"):
+			output(cmd_model_move(single_input("Model name?"), single_input("New location?")))
 		elif (cmd == "process_execute"):
 			output(cmd_process_execute(single_input("Process to execute?"), dict_input("Model bindings to use?")))
 		elif (cmd == "process_signature"):

+ 0 - 2
bootstrap/jit.alc

@@ -1,2 +0,0 @@
-Boolean function get_jit_enabled() = ?jit/get_jit_enabled
-Void function set_jit_enabled(a: Boolean) = ?jit/set_jit_enabled

+ 11 - 0
bootstrap/main.alc

@@ -0,0 +1,11 @@
+include "bootstrap/primitives.alc"
+include "utils.alh"
+include "core_algorithm.alh"
+include "task_manager.alh"
+
+Void function __main():
+	if (get_taskname() == "task_manager"):
+		task_management()
+	else:
+		new_task()
+	return!

+ 1 - 0
bootstrap/metamodels.alt

@@ -215,6 +215,7 @@ Void function initialize_AL(scd_location : String, export_location : String):
 	instantiate_link(model, "Inheritance", "", "return", "Statement")
 	instantiate_link(model, "Inheritance", "", "call", "Statement")
 	instantiate_link(model, "Inheritance", "", "declare", "Statement")
+	instantiate_link(model, "Inheritance", "", "output", "Statement")
 	instantiate_link(model, "Inheritance", "", "call", "Expression")
 	instantiate_link(model, "Inheritance", "", "access", "Expression")
 	instantiate_link(model, "Inheritance", "", "constant", "Expression")

+ 1 - 1
bootstrap/mini_modify.alc

@@ -414,7 +414,7 @@ String function cmd_read_attrs(model : Element, element_name : String):
 		attr_keys = dict_keys(attr_list)
 		while (0 < set_len(attr_keys)):
 			attr_key = set_pop(attr_keys)
-			result = string_join(result, attr_key) + " : " + cast_value(attr_list[attr_key]) + " = " + cast_string(read_attribute(model, element_name, attr_key)) + "\n"
+			result = string_join(result, attr_key) + " : " + cast_value(attr_list[attr_key]) + " = " + cast_value(read_attribute(model, element_name, attr_key)) + "\n"
 		return result!
 	else:
 		return "Element not found: " + element_name!

+ 2 - 2
bootstrap/model_management.alc

@@ -234,8 +234,8 @@ Element function model_join(models : Element, metamodel : Element, tracability_m
 							// Found a match for source and target, so create a link
 							new_name = instantiate_link(new_model, type, "", src_model + src_name, dst_model + dst_name)
 
-							if (new_name == ""):
-								log("ERROR: could not create a tracability link; ignoring")
+							//if (new_name == ""):
+							//	log("ERROR: could not create a tracability link; ignoring")
 	return new_model!
 	
 Element function model_split(merged_model : Element, models : Element, tracability : Boolean):

+ 8 - 2
bootstrap/object_operations.alc

@@ -203,24 +203,30 @@ String function readAssociationDestination(model : Element, name : String):
 Element function allAssociationDestinations(model : Element, name : String, association_type : String):
 	Element tmp
 	Element result
+	String val
 
 	result = set_create()
 	tmp = allOutgoingAssociationInstances(model, name, association_type)
 
 	while (set_len(tmp) > 0):
-		set_add(result, readAssociationDestination(model, set_pop(tmp)))
+		val = readAssociationDestination(model, set_pop(tmp))
+		if (val != ""):
+			set_add(result, val)
 
 	return result!
 
 Element function allAssociationOrigins(model : Element, name : String, association_type : String):
 	Element tmp
 	Element result
+	String val
 
 	result = set_create()
 	tmp = allIncomingAssociationInstances(model, name, association_type)
 
 	while (set_len(tmp) > 0):
-		set_add(result, readAssociationSource(model, set_pop(tmp)))
+		val = readAssociationSource(model, set_pop(tmp))
+		if (val != ""):
+			set_add(result, val)
 
 	return result!
 

+ 0 - 3
bootstrap/primitives.alc

@@ -33,15 +33,12 @@ Float function float_addition(a: Float, b: Float) = ?primitives/float_addition
 Float function float_subtraction(a: Float, b: Float) = ?primitives/float_subtraction
 Float function float_multiplication(a: Float, b: Float) = ?primitives/float_multiplication
 Float function float_division(a: Float, b: Float) = ?primitives/float_division
-Boolean function float_gt(a: Float, b: Float) = ?primitives/float_gt
 Boolean function float_lt(a: Float, b: Float) = ?primitives/float_lt
 Integer function integer_addition(a: Integer, b: Integer) = ?primitives/integer_addition
 Integer function integer_subtraction(a: Integer, b: Integer) = ?primitives/integer_subtraction
 Integer function integer_multiplication(a: Integer, b: Integer) = ?primitives/integer_multiplication
 Integer function integer_division(a: Integer, b: Integer) = ?primitives/integer_division
 Boolean function integer_lt(a: Integer, b: Integer) = ?primitives/integer_lt
-Element function list_insert(a: Element, b: Element, c: Integer) = ?primitives/list_insert
-Element function list_delete(a: Element, b: Integer) = ?primitives/list_delete
 String function string_join(a: String, b: String) = ?primitives/string_join
 String function string_get(a: String, b: Integer) = ?primitives/string_get
 Element function string_split(a: String, b: String) = ?primitives/string_split

+ 1 - 0
bootstrap/ramify.alc

@@ -85,6 +85,7 @@ Element function ramify(model : Element):
 	instantiate_node(new_model, "Class", "PostElement")
 	model_define_attribute(new_model, "PostElement", "label", False, "String")
 	model_define_attribute(new_model, "PostElement", "action", True, "ActionLanguage")
+	model_define_attribute(new_model, "PostElement", "__id__", True, "ActionLanguage")
 
 	// Association RHS_contains (RHS, PostElement) {}
 	instantiate_link(new_model, "Association", "RHS_contains", "RHS", "PostElement")

+ 37 - 9
bootstrap/semi_primitives.alc

@@ -89,7 +89,7 @@ Void function interruptable_sleep(a : Float):
 	__sleep(a, True)
 	return!
 
-Element function exec(first_instr : Element):
+Element mutable function exec(first_instr : Element):
 	// This does very ugly things, so beware!
 	// Basically, we dynamically construct an if True condition with as body the provided instructions
 	// after the if conditional, we append a return of an empty element, as we need a return at the end
@@ -404,7 +404,6 @@ Element function set_in_node(a: Element, b: Element):
 	return dict_in_node(a, b)!
 
 String function reverseKeyLookup(dict : Element, element : Element):
-	// TODO don't know if this AL will actually work...
 	Integer nr_in
 	Integer nr_out
 	Integer counter
@@ -422,21 +421,18 @@ String function reverseKeyLookup(dict : Element, element : Element):
 	return ""!
 
 Element function reverseKeyLookupMulti(dict : Element, element : Element):
-	// TODO don't know if this AL will actually work...
-	Integer nr_in
 	Integer nr_out
 	Integer counter
 	Element link
 	Element result
 
 	result = set_create()
-	nr_in = read_nr_in(element)
+	nr_out = read_nr_out(dict)
 	counter = 0
-	while (counter < nr_in):
-		if (element_eq(read_edge_src(read_in(element, counter)), dict)):
+	while (counter < nr_out):
+		if (value_eq(read_edge_dst(read_out(dict, counter)), element)):
 			// Got a match
-			set_add(result, read_edge_dst(read_out(read_in(element, counter), 0)))
-
+			set_add(result, read_edge_dst(read_out(read_out(dict, counter), 0)))
 		counter = counter + 1
 	
 	return result!
@@ -557,3 +553,35 @@ String function spawn(function : Element, arguments : Element):
 	dict_add_fast(read_root(), taskname, task_root)
 
 	return taskname!
+
+Element function list_insert(a : Element, b : Element, c : Integer):
+	Integer current
+	Element prev
+	Element new_prev
+
+	current = c
+	prev = b
+
+	while (current < list_len(a)):
+		new_prev = list_read(a, current)
+		dict_delete(a, current)
+		dict_add_fast(a, current, prev)
+		prev = new_prev
+		current = current + 1
+
+	dict_add_fast(a, current, prev)
+	
+	return a!
+
+Element function list_delete(a : Element, b : Integer):
+	Integer current
+
+	current = b
+	
+	while (current < (list_len(a) - 1)):
+		dict_delete(a, current)
+		dict_add_fast(a, current, a[current + 1])
+		current = current + 1
+
+	dict_delete(a, current)
+	return a!

+ 20 - 3
bootstrap/transform.alc

@@ -359,6 +359,8 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 	String value
 	String action
 	Element original_RHS_labels
+	String new_identifier
+	Element func
 
 	Element reverse
 	reverse = make_reverse_dictionary(schedule_model["model"])
@@ -389,6 +391,14 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 	while (list_len(labels_to_add) > 0):
 		// Add the elements linked to these labels
 		label = list_pop(labels_to_add, list_len(labels_to_add) - 1)
+
+		// Check if we have any requirement for the ID
+		if (element_eq(read_attribute(schedule_model, RHS_map[label], "__id__"), read_root())):
+			new_identifier = ""
+		else:
+			func = get_func_AL_model(import_node(read_attribute(schedule_model, RHS_map[label], "__id__")))
+			new_identifier = func(host_model, mapping)
+
 		if (is_edge(schedule_model["model"][RHS_map[label]])):
 			// Edge
 			src = read_attribute(schedule_model, reverse[cast_id(read_edge_src(schedule_model["model"][RHS_map[label]]))], "label")
@@ -399,7 +409,7 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 				// Both are present, so we can make the link
 				typename = read_type(schedule_model, RHS_map[label])
 				original_typename = string_substr(typename, 5, string_len(typename))
-				new_name = instantiate_link(host_model, original_typename, "", new_mapping[src], new_mapping[dst])
+				new_name = instantiate_link(host_model, original_typename, new_identifier, new_mapping[src], new_mapping[dst])
 				dict_add_fast(new_mapping, label, new_name)
 			else:
 				// Delay this a bit, until all are bound
@@ -409,13 +419,12 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 			// Create the node and add it
 			typename = read_type(schedule_model, RHS_map[label])
 			original_typename = string_substr(typename, 5, string_len(typename))
-			new_name = instantiate_node(host_model, original_typename, "")
+			new_name = instantiate_node(host_model, original_typename, new_identifier)
 			dict_add_fast(new_mapping, label, new_name)
 
 	Element attributes
 	String attribute
 	Element result
-	Element func
 
 	while (set_len(original_RHS_labels) > 0):
 		// Perform actions
@@ -535,16 +544,23 @@ Boolean function transform_atomic(host_model : Element, schedule_model : Element
 	// Execute the atomic transformation
 	Element mappings
 	Element mapping
+
+	//log("Executing rule: " + current)
+
 	mappings = full_match(host_model, schedule_model, current, True)
 
+	//log("Executing rule: " + current)
+
 	if (set_len(mappings) > 0):
 		// Pick one!
 		mapping = random_choice(set_to_list(mappings))
 		String RHS
 		RHS = set_pop(allAssociationDestinations(schedule_model, current, "RHSLink"))
 		rewrite(host_model, schedule_model, RHS, mapping)
+		//log("Rewrite OK")
 		return True!
 	else:
+		log("Rewrite failed")
 		return False!
 
 Boolean function transform_forall(host_model : Element, schedule_model : Element, current : String):
@@ -568,6 +584,7 @@ Boolean function transform_forall(host_model : Element, schedule_model : Element
 		mapping = set_pop(mappings)
 		RHS = set_pop(allAssociationDestinations(schedule_model, current, "RHSLink"))
 		rewrite(host_model, schedule_model, RHS, mapping)
+	//log("Rewrite OK")
 
 	return result!
 

+ 9 - 4
bootstrap/typing.alc

@@ -54,15 +54,20 @@ Void function set_type_mapping(model : Element, type_mapping_model : Element):
 
 Element function elements_typed_by(model : Element, type_name : String):
 	Element result
-	result = reverseKeyLookupMulti(get_type_mapping_as_dict(model), type_name)
+	Element temp_result
+	String temp
+
+	result = set_create()
+	temp_result = reverseKeyLookupMulti(get_type_mapping_as_dict(model), type_name)
+	while (set_len(temp_result) > 0):
+		temp = set_pop(temp_result)
+		if (dict_in(model["model"], temp)):
+			set_add(result, temp)
 	return result!
 
 Element function get_type_mapping_as_dict(model : Element):
 	return model["type_mapping"]!
 
-Element function get_elements_typed_by(model : Element, type : String):
-	return reverseKeyLookupMulti(model["type_mapping"], type)!
-
 String function read_type(model : Element, name : String):
 	String result
 	Element tm

+ 2 - 0
bootstrap/utils.alc

@@ -19,7 +19,9 @@ String function JSON_print(model : Element):
 
 	while (set_len(keys_m) > 0):
 		v_m = set_pop(keys_m)
+		log("Check " + v_m)
 		type = read_type(model["metamodel"], read_type(model, v_m))
+		log("Type: " + type)
 
 		if (bool_or(type == "Class", type == "Association")):
 			if (bool_not(first)):

+ 116 - 124
doc/actionlanguage.rst

@@ -282,127 +282,119 @@ Apart from the minimal syntax, the Modelverse supports a wide library of functio
 These functions are all built on top of the previously defined constructs.
 A list of these functions is shown below.
 
-* Boolean function value_eq(a: Element, b: Element)
-* Boolean function value_neq(a: Element, b: Element)
-* Boolean function bool_and(a: Boolean, b: Boolean)
-* Boolean function bool_or(a: Boolean, b: Boolean)
-* Boolean function bool_not(a: Boolean)
-* Element function create_node()
-* Element function create_edge(a: Element, b: Element)
-* Element function create_value(a: Element)
-* Boolean function is_edge(a: Element)
-* Integer function read_nr_out(a: Element)
-* Element function read_out(a: Element, b: Integer)
-* Integer function read_nr_in(a: Element)
-* Element function read_in(a: Element, b: Integer)
-* Element function read_edge_src(a: Element)
-* Element function read_edge_dst(a: Element)
-* Boolean function delete_element(a: Element)
-* Boolean function element_eq(a: Element, b: Element)
-* Boolean function element_neq(a: Element, b: Element)
-* Float function cast_i2f(a: Integer)
-* String function cast_i2s(a: Integer)
-* Boolean function cast_i2b(a: Integer)
-* Integer function cast_f2i(a: Float)
-* Boolean function cast_f2b(a: Float)
-* String function cast_f2s(a: Float)
-* Integer function cast_s2i(a: String)
-* Float function cast_s2f(a: String)
-* Boolean function cast_s2b(a: String)
-* Integer function cast_b2i(a: Boolean)
-* Float function cast_b2f(a: Boolean)
-* String function cast_b2s(a: Boolean)
-* String function cast_e2s(a: Element)
-* String function cast_a2s(a: Action)
-* String function cast_v2s(a: Element)
-* String function cast_id2s(a: Element)
-* Element function dict_add(a: Element, b: Element, c: Element)
-* Element function dict_add_fast(a: Element, b: Element, c: Element)
-* Element function dict_delete(a: Element, b: Element)
-* Element function dict_delete_node(a: Element, b: Element)
-* Element function dict_read(a: Element, b: Element)
-* Element function dict_read_edge(a: Element, b: Element)
-* Element function dict_read_node(a: Element, b: Element)
-* Integer function dict_len(a: Element)
-* Boolean function dict_in(a: Element, b: Element)
-* Boolean function dict_in_node(a: Element, b: Element)
-* Element function dict_keys(a: Element)
-* Float function float_addition(a: Float, b: Float)
-* Float function float_subtraction(a: Float, b: Float)
-* Float function float_multiplication(a: Float, b: Float)
-* Float function float_division(a: Float, b: Float)
-* Float function float_neg(a: Float)
-* Boolean function float_gt(a: Float, b: Float)
-* Boolean function float_gte(a: Float, b: Float)
-* Boolean function float_lt(a: Float, b: Float)
-* Boolean function float_lte(a: Float, b: Float)
-* Integer function integer_addition(a: Integer, b: Integer)
-* Integer function integer_subtraction(a: Integer, b: Integer)
-* Integer function integer_multiplication(a: Integer, b: Integer)
-* Integer function integer_division(a: Integer, b: Integer)
-* Integer function integer_modulo(a: Integer, b: Integer)
-* Boolean function integer_gt(a: Integer, b: Integer)
-* Boolean function integer_gte(a: Integer, b: Integer)
-* Boolean function integer_lt(a: Integer, b: Integer)
-* Boolean function integer_lte(a: Integer, b: Integer)
-* Boolean function integer_neg(a: Integer)
-* Element function list_read(a: Element, b: Integer)
-* Element function list_append(a: Element, b: Element)
-* Element function list_insert(a: Element, b: Element, c: Integer)
-* Element function list_delete(a: Element, b: Integer)
-* Integer function list_len(a: Element)
-* Boolean function list_in(a : Element, b : Element)
-* Element function set_add(a: Element, b: Element)
-* Element function set_add_node(a: Element, b: Element)
-* Element function set_pop(a: Element)
-* Element function set_read(a : Element)
-* Element function set_remove(a: Element, b: Element)
-* Boolean function set_in(a: Element, b: Element)
-* Element function set_remove_node(a: Element, b: Element)
-* Element function set_in_node(a: Element, b: Element)
-* Integer function set_len(a: Element)
-* String function string_join(a: String, b: String)
-* String function string_get(a: String, b: Integer)
-* String function string_substr(a: String, b: Integer, c: Integer)
-* Integer function string_len(a: String)
-* Element function string_split(a: String, b: String)
-* Boolean function string_startswith(a: String, b: String)
-* String function log(a: String)
-* Element function read_root()
-* Element function read_taskroot()
-* Element function input()
-* Element function output(a : Element)
-* Boolean function is_physical_int(a : Element)
-* Boolean function is_physical_float(a : Element)
-* 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)
-* Float function time()
-* String function hash(a : String)
-* Void function sleep(a : Float)
-* Void function interruptable_sleep(a : Float)
-* Element function exec(a : Element)
-* Element function resolve(var_name : String)
-* Boolean function has_input()
-* Element function list_pop(lst : Element, index : Integer)
-* Element function list_pop_final(lst : Element)
-* Element function set_copy(set : Element)
-* String function set_to_string(set : Element)
-* String function list_to_string(set : Element)
-* String function dict_to_string(dict : Element)
-* Element function set_overlap(sa : Element, sb : Element)
-* Element function set_equality(sa : Element, sb : Element)
-* Element function dict_eq(da : Element, db : Element)
-* Element function dict_copy(dict : Element)
-* Element function set_to_list(s : Element)
-* Element function create_tuple(a : Element, b : Element)
-* Void function dict_overwrite(a : Element, b : Element, c : Element)
-* Void function set_merge(sa : Element, sb : Element)
-* Element function make_reverse_dictionary(dict : Element)
-* Element function set_create()
-* Element function list_create()
-* Element function dict_create()
-* String function reverseKeyLookup(a: Element, b: Element)
-* Element function reverseKeyLookupMulti(a: Element, b: Element)
-* Element function dict_values(dict : Element)
+* *Boolean function value_eq(a: Element, b: Element)*
+* *Boolean function value_neq(a: Element, b: Element)*
+* *Boolean function bool_and(a: Boolean, b: Boolean)*
+* *Boolean function bool_or(a: Boolean, b: Boolean)*
+* *Boolean function bool_not(a: Boolean)*
+* *Element function create_node()*
+* *Element function create_edge(a: Element, b: Element)*
+* *Element function create_value(a: Element)*
+* *Boolean function is_edge(a: Element)*
+* *Integer function read_nr_out(a: Element)*
+* *Element function read_out(a: Element, b: Integer)*
+* *Integer function read_nr_in(a: Element)*
+* *Element function read_in(a: Element, b: Integer)*
+* *Element function read_edge_src(a: Element)*
+* *Element function read_edge_dst(a: Element)*
+* *Boolean function delete_element(a: Element)*
+* *Boolean function element_eq(a: Element, b: Element)*
+* *Boolean function element_neq(a: Element, b: Element)*
+* *Float function cast_float(a: Element)*
+* *String function cast_string(a: Element)*
+* *Boolean function cast_boolean(a: Element)*
+* *Integer function cast_integer(a: Element)*
+* *String function cast_id(a: Element)*
+* *String function cast_value(a: Element)*
+* *Element function dict_add(a: Element, b: Element, c: Element)*
+* *Element function dict_add_fast(a: Element, b: Element, c: Element)*
+* *Element function dict_delete(a: Element, b: Element)*
+* *Element function dict_delete_node(a: Element, b: Element)*
+* *Element function dict_read(a: Element, b: Element)*
+* *Element function dict_read_edge(a: Element, b: Element)*
+* *Element function dict_read_node(a: Element, b: Element)*
+* *Integer function dict_len(a: Element)*
+* *Boolean function dict_in(a: Element, b: Element)*
+* *Boolean function dict_in_node(a: Element, b: Element)*
+* *Element function dict_keys(a: Element)*
+* *Float function float_addition(a: Float, b: Float)*
+* *Float function float_subtraction(a: Float, b: Float)*
+* *Float function float_multiplication(a: Float, b: Float)*
+* *Float function float_division(a: Float, b: Float)*
+* *Float function float_neg(a: Float)*
+* *Boolean function float_gt(a: Float, b: Float)*
+* *Boolean function float_gte(a: Float, b: Float)*
+* *Boolean function float_lt(a: Float, b: Float)*
+* *Boolean function float_lte(a: Float, b: Float)*
+* *Integer function integer_addition(a: Integer, b: Integer)*
+* *Integer function integer_subtraction(a: Integer, b: Integer)*
+* *Integer function integer_multiplication(a: Integer, b: Integer)*
+* *Integer function integer_division(a: Integer, b: Integer)*
+* *Integer function integer_modulo(a: Integer, b: Integer)*
+* *Boolean function integer_gt(a: Integer, b: Integer)*
+* *Boolean function integer_gte(a: Integer, b: Integer)*
+* *Boolean function integer_lt(a: Integer, b: Integer)*
+* *Boolean function integer_lte(a: Integer, b: Integer)*
+* *Boolean function integer_neg(a: Integer)*
+* *Element function list_read(a: Element, b: Integer)*
+* *Element function list_append(a: Element, b: Element)*
+* *Element function list_insert(a: Element, b: Element, c: Integer)*
+* *Element function list_delete(a: Element, b: Integer)*
+* *Integer function list_len(a: Element)*
+* *Boolean function list_in(a : Element, b : Element)*
+* *Element function set_add(a: Element, b: Element)*
+* *Element function set_add_node(a: Element, b: Element)*
+* *Element function set_pop(a: Element)*
+* *Element function set_read(a : Element)*
+* *Element function set_remove(a: Element, b: Element)*
+* *Boolean function set_in(a: Element, b: Element)*
+* *Element function set_remove_node(a: Element, b: Element)*
+* *Element function set_in_node(a: Element, b: Element)*
+* *Integer function set_len(a: Element)*
+* *String function string_join(a: String, b: String)*
+* *String function string_get(a: String, b: Integer)*
+* *String function string_substr(a: String, b: Integer, c: Integer)*
+* *Integer function string_len(a: String)*
+* *Element function string_split(a: String, b: String)*
+* *Boolean function string_startswith(a: String, b: String)*
+* *String function log(a: String)*
+* *Element function read_root()*
+* *Element function read_taskroot()*
+* *Element function input()*
+* *Element function output(a : Element)*
+* *Boolean function is_physical_int(a : Element)*
+* *Boolean function is_physical_float(a : Element)*
+* *Boolean function is_physical_string(a : Element)*
+* *Boolean function is_physical_action(a : Element)*
+* *Boolean function is_physical_boolean(a : Element)*
+* *Boolean function is_physical_none(a : Element)*
+* *Boolean function is_error(a : Element)*
+* *Boolean function has_value(a : Element)*
+* *Float function time()*
+* *String function hash(a : String)*
+* *Void function sleep(a : Float)*
+* *Void function interruptable_sleep(a : Float)*
+* *Element function exec(a : Element)*
+* *Element function resolve(var_name : String)*
+* *Boolean function has_input()*
+* *Element function list_pop(lst : Element, index : Integer)*
+* *Element function list_pop_final(lst : Element)*
+* *Element function set_copy(set : Element)*
+* *String function set_to_string(set : Element)*
+* *String function list_to_string(set : Element)*
+* *String function dict_to_string(dict : Element)*
+* *Element function set_overlap(sa : Element, sb : Element)*
+* *Element function set_equality(sa : Element, sb : Element)*
+* *Element function dict_eq(da : Element, db : Element)*
+* *Element function dict_copy(dict : Element)*
+* *Element function set_to_list(s : Element)*
+* *Element function create_tuple(a : Element, b : Element)*
+* *Void function dict_overwrite(a : Element, b : Element, c : Element)*
+* *Void function set_merge(sa : Element, sb : Element)*
+* *Element function make_reverse_dictionary(dict : Element)*
+* *Element function set_create()*
+* *Element function list_create()*
+* *Element function dict_create()*
+* *String function reverseKeyLookup(a: Element, b: Element)*
+* *Element function reverseKeyLookupMulti(a: Element, b: Element)*
+* *Element function dict_values(dict : Element)*

+ 0 - 8
doc/concrete_syntax.rst

@@ -1,8 +0,0 @@
-Concrete Syntax
-===============
-
-Concrete syntax is an unavoidable aspect of modelling if you want to have decent usability.
-However, as the Modelverse is only a back-end, we leave concrete syntax up to the front-end to specify.
-Nonetheless, we have described and implemented a relatively simple way of supporting flexible concrete syntax, in an explicitly defined way.
-
-TODO

+ 1 - 0
doc/developer.rst

@@ -13,3 +13,4 @@ Using the Modelverse as a Developer
    Bootstrap <bootstrap>
    Internals <internal>
    Interfaces <interface>
+   JIT interpreter <jit>

+ 2 - 0
doc/index.rst

@@ -14,6 +14,8 @@ We make the distinction between three types of users of the Modelverse: modeller
 Depending on your goals of using the Modelverse, you will fall into one of these categories.
 Due to the design of the Modelverse, where everything is a model, the hierarchy is cumulative: language require knowledge of modelling, and developers require knowledge of language engineer and modelling.
 
+Example scripts used for some of our papers can be found in the *examples* folder.
+
 .. toctree::
    :maxdepth: 2
     

+ 6 - 2
doc/interaction.rst

@@ -48,11 +48,14 @@ For most users, there are only three relevant scripts, none of them taking param
 Wrapper
 -------
 
-In addition to these scripts, we provide a simple Python-based wrapper for the Modelverse.
+Most often, however, the Modelverse is not used using the raw interface.
+Therefore, additionally we provide a simple Python-based wrapper for the Modelverse, which can be included in arbitrary scripts.
 As the Modelverse can run as a service, wrappers can be created in any language that supports XML/HTTPRequests.
 By default, a Python wrapper is provided, which is discussed in this documentation.
 This Python wrapper was used by a variety of MvI implementations supported today.
 Tools can include all Modelverse operations merely by including the *modelverse.py* file from the *wrappers* folder.
+It is this interface that is used throughout this documentation, although other interfaces are highly similar.
+Note that the Python interface is a synchronous, and therefore blocking, interface.
 
 The wrapper provides all necessary (meta-)modelling operations that can be used by the MvI.
 As the Modelverse is independent of its (visual/textual) user interface, we only discuss the Modelverse wrapper in this documentation.
@@ -74,7 +77,8 @@ For that, you must start up a Modelverse at your own system by invoking the comm
     python scripts/run_local_modelverse.py
 
 Afterwards, connect to the local Modelverse through the usual *init* operation.
-Note that, for a local Modelverse, the init can be left empty::
+For a local Modelverse, the init can be left empty.
+This call might block for some time if the Modelverse server is still starting up::
 
     >>> init()
 

+ 4 - 0
doc/jit.rst

@@ -0,0 +1,4 @@
+JIT interpreter
+===============
+
+TODO

+ 0 - 1
doc/language_engineer.rst

@@ -14,5 +14,4 @@ When defining a language, the language engineer will mostly use the same operati
    Transformations <transformations>
    Operations <operations>
    Services <services>
-   Concrete Syntax <concrete_syntax>
    Conformance <conformance>

+ 15 - 1
doc/modeller_modellanguage.rst

@@ -58,7 +58,7 @@ Example: Finite State Automata
 ------------------------------
 
 Next we use a simple Finite State Automata example model.
-This will introduce two new concepts: hierarchy and code attributes.
+This will introduce two new concepts: hierarchy, long strings, and code attributes.
 
 Hierarchy
 ^^^^^^^^^
@@ -122,6 +122,20 @@ As there is no difference between *Contains* and *Transition*, there is nothing
 In this case, the state *state 1* and *state 2* are actually at the same level, with a transition between them.
 This can get rather confusing, and is therefore discouraged.
 
+Long string attributes
+^^^^^^^^^^^^^^^^^^^^^^
+
+Sometimes longer string values are required in attributes, for example as code blocks or descriptions of elements.
+In this case, three double quotes are used to delimit this string, similar to Python.
+Note that an ordinary double quote is not allowed within this long string attribute, due to limitations of the parser::
+
+    State s1 {
+        description = """
+        This is a lenghty description of the state.
+        In this state, the execution will start.
+        """
+    }
+
 Code
 ^^^^
 

+ 36 - 12
doc/modelling.rst

@@ -10,9 +10,14 @@ Both the *P2T* and *T2P*"arcs have a *weight*.
 This information is stored in the metamodel, which we will define later on.
 For now, assume that the metamodel is stored in the Modelverse using the name *PetriNets*.
 
-Creating a model
+Model Management
 ----------------
 
+Modellers have access to a variety of model management operations, making it possible to create, read, update, and delete complete models.
+
+Create
+^^^^^^
+
 Creating a new instance of PetriNets is simple, and can be done using the *model_add* operation of the wrapper::
 
     >>> model_add("models/my_pn", "formalisms/PetriNets")
@@ -22,6 +27,9 @@ This name is available to all users, and is therefore a unique identifier.
 The second parameter is the metamodel that we want to use to conform to.
 The value needs to be a name that is available in the Modelverse, and readable to the current user.
 
+Read
+^^^^
+
 To get a list of currently available models, users can query the Modelverse with the *model_list* operation::
 
     >>> model_list("")
@@ -42,12 +50,29 @@ Depending on permissions, not all folders can be listed::
     >>> model_list("administration")
     PermissionDenied("administration")
 
+Update
+^^^^^^
+
+Models can be updated in the sense that they can be moved.
+This is the operation *model_move*, which takes a model and moves it to the specified location.
+There is no output to this operation::
+
+    >>> model_move("models/my_pn", "models/my_new_pn")
+
+Delete
+^^^^^^
+
+Finally, models can be deleted using the *model_delete* operations.
+Model deletion is permanent and cannot be reverted::
+
+    >>> model_delete("models/my_pn")
+
 Modifying a model
 -----------------
 
-Now that we have created our model, we can start modifying it.
-To do so, we have access to several operations offered by the Modelverse.
+Apart from operations at the model management level, where models are considered as atomic, several operations are provided to operate on the model contents.
 We categorize them by their effects on the Modelverse: create, read, or delete.
+Updates are not allowed, and must be expanded in individual delete and create operation.
 Create and delete operations are only allowed when the user has write permission to the model, which users have by default on their own models.
 
 Create
@@ -58,11 +83,11 @@ Create
         >>> instantiate("models/my_pn", "Place")
         __12345
 
-    The operation requires the model on which we are working, and the type of the element you want to instantiate.
-    When successful, the operation returns the identifier that can be used in future operations.
-    This identifier has no value within the model, and should only be used as a handle to that specific model element.
+   The operation requires the model on which we are working, and the type of the element you want to instantiate.
+   When successful, the operation returns the identifier that can be used in future operations.
+   This identifier has no value within the model, and should only be used as a handle to that specific model element.
 
-    When instantiating an edge, the optional *edge* parameter must be passed with the identifiers to connect::
+   When instantiating an edge, the optional *edge* parameter must be passed with the identifiers to connect::
         
         >>> instantiate("models/my_pn", "Place")
         p1
@@ -86,17 +111,17 @@ Create
 Read
 ^^^^
 
-1. *read* reads out basic information about a queried element, such as its type and the source and target (if it is an edge)::
+1. *read_info* reads out basic information about a queried element, such as its type and the source and target (if it is an edge)::
 
         >>> instantiate("models/my_pn", "Place")
         p1
-        >>> read("models/my_pn", "p1")
+        >>> read_info("models/my_pn", "p1")
         ("Place, None)
         >>> instantiate("models/my_pn", "Transition")
         t1
         >>> instantiate("models/my_pn", "P2T", edge=("p1", "t1"))
         p2t1
-        >>> read("models/my_pn", "p2t1")
+        >>> read_info("models/my_pn", "p2t1")
         ("P2T", ("p1", "t1"))
 
 2. *read_attrs* reads out the attributes of a specific element, in a dictionary form.
@@ -159,13 +184,12 @@ Read
 
 9. *connections_between* reads out the set of all association types that can be created between two elements in the model.
    This also takes into account inheritance information.
+   If no associations are allowed, the list is empty.
    For example, to find out which association types can connect a place and transition::
 
         >>> connections_between("models/my_pn", "p1", "t1")
         ["P2T"]
 
-    If no associations are allowed, the list is empty.
-
 10. *all_instances* read out the set of all instances of a specific type in the model.
     For example, to find all Places in our PetriNet model::
 

+ 2 - 2
doc/transformations.rst

@@ -99,8 +99,7 @@ An example specification is shown below, which will copy the highest number of t
 
         constraint = $
             Boolean function constraint(host_model : Element, mapping : Element):
-                return value_eq(read_attribute(host_model, mapping["pn_place_master"], "name"), 
-                                read_attribute(host_model, mapping["pn_place_slave"], "name"))!
+                return value_eq(read_attribute(host_model, mapping["pn_place_master"], "name"), read_attribute(host_model, mapping["pn_place_slave"], "name"))!
                 $
     }
     RHS {
@@ -111,6 +110,7 @@ An example specification is shown below, which will copy the highest number of t
             label = "pn_place_slave"
             value_tokens = $
                 Integer function value(host_model : Element, name : Element, mapping : Element):
+                    return read_attribute(host_model, mapping["pn_place_master"], "tokens")!
                 $
         }
     }

+ 57 - 19
doc/wrappers.rst

@@ -48,7 +48,6 @@ Functions
    * To create a connection to a local Modelverse.
 
      >>> init()
-     Done
 
    * To create a connection to the Modelverse running remotely.
 
@@ -305,13 +304,14 @@ Functions
 
      >>> transformation_add_MANUAL({"pn": "formalisms/PetriNets", "requirements": "formalisms/Requirements"}, {"pn": "formalisms/PetriNets"}, "models/pn_refine_req")
 
-.. function:: transformation_execute_AL(operation_name, input_models_dict, output_models_dict, callback=lambda i: None)
+.. function:: transformation_execute_AL(operation_name, input_models_dict, output_models_dict, statechart=None)
 
    Executes the Action Language model *operation_name* with *input_models_dict* as inputs and *output_models_dict* as outputs.
    For both dicts, the contents describe the mapping between the parameter names of the operation to the names in the Modelverse.
    Values in *input_models_dict* must be existing models, whereas values in *output_models_dict* can be non-existing upon invocation.
-   A *callback* function can be defined when the action language model requires user input or output.
-   This callback function can be used to communicate with the executing action language directly.
+   A *statechart* tuple can be defined when the action language model requires user input or output.
+   This is used to communicate with the executing code directly.
+   For more information about this, refer to the execution of transformations.
 
    Examples:
 
@@ -319,13 +319,6 @@ Functions
 
      >>> transformation_execute_AL("models/pn_analyze", {"pn": "models/my_pn"}, {"graph": "models/my_pn_reachability"})
 
-   * To execute reachability analysis which prompts the user, for example because it is a debugging prompt.
-
-     >>> def callback(value):
-     ...     print(value)       # Prints out the prompt of the execution of the Action Language fragment
-     ...     return raw_input() # Sends a raw request from the user to the Modelverse, consumed in the Action Language
-     >>> transformation_execute_AL("models/pn_simulate", {"pn": "models/my_pn"}, {"graph": "models/my_pn_reachability"}, callback)
-
 .. function:: transformation_execute_MANUAL(operation_name, input_models_dict, output_models_dict, callback=lambda i: None)
 
    Executes the manual model operation *operation_name*.
@@ -343,7 +336,7 @@ Functions
      ...     instantiate(None, "pn/P2T", (p1, t1))
      >>> transformation_execute_MANUAL("models/pn_refine", {"pn": "models/my_pn"}, {"pn": "models/my_pn"}, callback)
 
-.. function:: transformation_execute_MT(operation_name, input_models_dict, output_models_dict, callback=lambda i: None)
+.. function:: transformation_execute_MT(operation_name, input_models_dict, output_models_dict, statechart=None)
 
    Executes the model transformation operation *operation_name*.
    Identical to *transformation_execute_AL*.
@@ -354,13 +347,6 @@ Functions
 
      >>> transformation_execute_MT("models/pn_simulate", {"pn": "models/my_pn"}, {"pn": "models/my_simulated_pn"})
 
-   * To execute a model transformation which prompts the user.
-
-     >>> def callback(value):
-     ...     print(value)
-     ...     return raw_input()
-     >>> transformation_execute_MT("models/pn_simulate_prompt", {"pn": "models/my_pn"}, {"pn": "models/my_simulated_pn"}, callback)
-
 .. function:: process_execute(process_name, prefix, callbacks)
 
    Execute the process model stored as *process_name*.
@@ -368,6 +354,7 @@ Functions
    Note that this applies to the resolution of input models as well.
    Optionally, a dictionary of *callbacks* can be defined with as key the operation that is being executed, and value the actual callback.
    The callbacks must be similarly defined just like how they were defined in the individual *transformation_execute* operations.
+   This means that the callback might very well be a tuple for a statechart instance.
 
    Examples:
 
@@ -1220,6 +1207,57 @@ Below is a list of all exceptions that the wrappers can raise, together with a s
      >>> element_list()
      UnknownMetamodellingHierarchy("models/my_pn")
 
+SCCD
+----
+
+An SCCD interface is created, which has exactly the same interface.
+Actually, the Python interface presented before is built using this SCCD interface.
+The operations are identical and have the same signature, although they are invoked differently.
+
+To make a request to the Modelverse, an event has to be raised called *action*.
+The first parameter of this event is the operation to invoke, as a string (*e.g.*, 'read_info').
+The second parameter specifies an ID that can be used in the response event to identify which event this is the response to.
+The third parameter is unused.
+The fourth parameter is a list of all the parameters to this function (*e.g.*, ["my_pn"]).
+For example::
+
+    <raise event="action">
+        <parameter expr="'read_info'"/>
+        <parameter expr="None"/>
+        <parameter expr="None"/>
+        <parameter expr="['my_pn']"/>
+    </raise>
+
+When this request is processed, the Modelverse will reply with the *mv_result* event, containing the result.
+The first parameter is the ID passed on in the original request.
+The second parameter contains the result.
+It is possible to wait on this event as follows::
+
+    <transition event="mv_result" target=".">
+        <parameter name="ID"/>
+        <parameter name="result"/>
+        <script>
+            print("Response: " + str(result))
+        </script>
+    </transition>
+
+If something went wrong, the event *mv_exception* will be raised instead::
+
+    <transition event="mv_exception" target=".">
+        <parameter name="ID"/>
+        <parameter name="exception_name"/>
+        <parameter name="exception"/>
+        <script>
+            print("Exception: " + str(exception_name))
+            print(exception)
+        </script>
+    </transition>
+
+The use of the SCCD interface is particularly interesting in case asynchronous communication is required.
+In contrast to the Python interface, requests don't block, making it possible to do additional computations in the background, or even work in a multi-threaded context.
+Note, however, that the SCCD interface is more difficult to use with callbacks and other statecharts, as you will have to manually make the linkage with ports.
+For this, we refer to the implementation.
+
 Custom
 ------
 

+ 40 - 0
examples/SCCD_execute.py

@@ -0,0 +1,40 @@
+import sys
+sys.path.append("wrappers")
+from modelverse import *
+
+init()
+login("admin", "admin")
+
+model_add("test/SCCD", "formalisms/SimpleClassDiagrams", open("models/SCCD/metamodels/SCCD.mvc", 'r').read())
+model_add("test/SCCD_Trace", "formalisms/SimpleClassDiagrams", open("models/DiscreteEventTrace/metamodels/trace.mvc", 'r').read())
+
+model_add("test/my_SCCD", "test/SCCD", open("models/SCCD/models/dynamic_trafficlight.mvc", 'r').read())
+
+#transformation_add_AL({"SCCD": "test/SCCD"}, {"trace": "test/SCCD_Trace"}, "test/SCCD_execute_afap", open("models/SCCD/transformations/execute.alc", 'r').read().replace("afap = False", "afap = True"))
+transformation_add_AL({"SCCD": "test/SCCD"}, {"trace": "test/SCCD_Trace"}, "test/SCCD_execute_afap", open("models/SCCD/transformations/execute.alc", 'r').read())
+
+import poll_print
+ctrl = poll_print.Controller(keep_running=False)
+
+thrd = threading.Thread(target=ctrl.start)
+thrd.daemon = True
+thrd.start()
+
+def input_thread():
+    import select
+    while thrd.is_alive():
+        if select.select([sys.stdin], [], [], 0.1)[0]:
+            ctrl.addInput(Event("raw_inp", "user_inp", [sys.stdin.readline().strip()]))
+
+thrd2 = threading.Thread(target=input_thread)
+thrd2.daemon = True
+thrd2.start()
+
+transformation_execute_AL("test/SCCD_execute_afap", {"SCCD": "test/my_SCCD"}, {"trace": "test/my_SCCD_trace"}, statechart=(ctrl, "inp", "outp"))
+
+alter_context("test/my_SCCD_trace", "test/SCCD_Trace")
+lst = element_list_nice("test/my_SCCD_trace")
+
+lst.sort(key=lambda i: (i["timestamp"], i["name"]))
+result = [(i["timestamp"], str(i["name"])) for i in lst if i["name"] not in ["updateTimerValue", "updateTimerColour", "resetTimer"]]
+print(result)

+ 16 - 0
examples/analyze_LoLa.py

@@ -0,0 +1,16 @@
+import sys
+sys.path.append("wrappers/")
+from modelverse import *
+
+init()
+login("admin", "admin")
+
+model_add("formalisms/PetriNets", "formalisms/SimpleClassDiagrams", open("models/PetriNets/metamodels/PetriNets.mvc", 'r').read())
+model_add("formalisms/Query", "formalisms/SimpleClassDiagrams", open("models/SafetyQuery/metamodels/query.mvc", 'r').read())
+
+model_add("models/PN", "formalisms/PetriNets", open("models/PetriNets/models/critical_section_with_check.mvc", 'r').read())
+model_add("models/Query", "formalisms/Query", open("models/SafetyQuery/models/both_criticals_enabled.mvc", 'r').read())
+
+transformation_add_AL({"PN": "formalisms/PetriNets", "Query": "formalisms/Query"}, {}, "models/analyze_lola", open("models/PetriNets/transformations/analyze_lola.alc", 'r').read())
+
+transformation_execute_AL("models/analyze_lola", {"PN": "models/PN", "Query": "models/Query"}, {})

+ 30 - 0
examples/debug_DEVS.py

@@ -0,0 +1,30 @@
+import sys
+sys.path.append("wrappers")
+from modelverse import *
+
+init()
+login("admin", "admin")
+
+model_add("formalisms/ParallelDEVS", "formalisms/SimpleClassDiagrams", open("models/ParallelDEVS/metamodels/PDEVS.mvc", 'r').read())
+model_add("models/produce_consume_pdevs", "formalisms/ParallelDEVS", open("models/ParallelDEVS/models/produce_consume.mvc", 'r').read())
+
+transformation_add_AL({"ParallelDEVS": "formalisms/ParallelDEVS"}, {}, "models/paralleldevs_simulator", open("models/ParallelDEVS/transformations/simulate_interactive.alc", "r").read())
+
+import poll_print
+ctrl = poll_print.Controller(keep_running=False)
+
+thrd = threading.Thread(target=ctrl.start)
+thrd.daemon = True
+thrd.start()
+
+def input_thread():
+    import select
+    while thrd.is_alive():
+        if select.select([sys.stdin], [], [], 0.1)[0]:
+            ctrl.addInput(Event("raw_inp", "user_inp", [sys.stdin.readline().strip()]))
+
+thrd2 = threading.Thread(target=input_thread)
+thrd2.daemon = True
+thrd2.start()
+
+transformation_execute_AL("models/paralleldevs_simulator", {"ParallelDEVS": "models/produce_consume_pdevs"}, {}, statechart=(ctrl, "inp", "outp"))

+ 43 - 0
examples/live_modelling_CTCBD.py

@@ -0,0 +1,43 @@
+import sys
+sys.path.append("wrappers")
+from modelverse import *
+import time
+
+init()
+login("admin", "admin")
+
+### live modelling CTCBD
+
+model_add("formalisms/CTCBD/Design_MM", "formalisms/SimpleClassDiagrams", open("models/CTCBD/metamodels/CTCBD_MM.mvc", 'r').read())
+model_add("formalisms/DTCBD/PartialRuntime_MM", "formalisms/SimpleClassDiagrams", open("models/DTCBD/metamodels/DTCBD_MM_partial_runtime.mvc", 'r').read())
+model_add("formalisms/DTCBD/FullRuntime_MM", "formalisms/SimpleClassDiagrams", open("models/DTCBD/metamodels/DTCBD_MM_runtime.mvc", 'r').read())
+
+model_add("models/CTCBD_model", "formalisms/CTCBD/Design_MM", open("models/CTCBD/models/spring.mvc", 'r').read())
+
+transformation_add_MANUAL({"Design": "formalisms/CTCBD/Design_MM"}, {"Design": "formalisms/CTCBD/Design_MM"}, "models/CTCBD/edit")
+
+def trace_D2P(model):
+    instantiate(model, "Association", ("Design/Block", "PartialRuntime/Block"), ID="D2P_block")
+
+transformation_add_MT({"Design": "formalisms/CTCBD/Design_MM", "PartialRuntime": "formalisms/DTCBD/PartialRuntime_MM"}, {"PartialRuntime": "formalisms/DTCBD/PartialRuntime_MM"}, "models/CTCBD/toRuntime", open("models/CTCBD/transformations/to_partial_runtime.mvc", 'r').read(), trace_D2P)
+
+def trace_P2F(model):
+    instantiate(model, "Association", ("PartialRuntime/Block", "FullRuntime/Block"), ID="P2F_block")
+
+transformation_add_AL({"PartialRuntime": "formalisms/DTCBD/PartialRuntime_MM", "FullRuntime": "formalisms/DTCBD/FullRuntime_MM"}, {"NewFullRuntime": "formalisms/DTCBD/FullRuntime_MM"}, "models/DTCBD/merge", open("models/DTCBD/transformations/merge.alc", 'r').read(), trace_P2F)
+transformation_add_AL({"FullRuntime": "formalisms/DTCBD/FullRuntime_MM"}, {"FullRuntime": "formalisms/DTCBD/FullRuntime_MM"}, "models/DTCBD/simulate", open("models/DTCBD/transformations/simulate.alc", 'r').read())
+transformation_add_AL({}, {}, "models/DTCBD/restartSim", open("models/generic/restart_simulation.alc", 'r').read())
+
+model_add("models/live_modelling_CTCBD", "formalisms/ProcessModel", open("models/CTCBD/PM_live_modelling.mvc", 'r').read())
+
+def modify_model(model):
+    elements = element_list_nice(model)
+    for e in elements:
+        if e.get("value", None) == 10.0:
+            attr_assign(model, e["id"], "value", 100.0)
+            break
+    else:
+        while 1:
+            time.sleep(1)
+
+process_execute("models/live_modelling_CTCBD", {"design_model": "models/CTCBD_model"}, {"models/CTCBD/edit": modify_model})

+ 53 - 0
examples/live_modelling_DTCBD.py

@@ -0,0 +1,53 @@
+import sys
+sys.path.append("wrappers")
+from modelverse import *
+
+init()
+login("admin", "admin")
+
+### live modelling DTCBD
+
+model_add("formalisms/DTCBD/Design_MM", "formalisms/SimpleClassDiagrams", open("models/DTCBD/metamodels/DTCBD_MM.mvc", 'r').read())
+model_add("formalisms/DTCBD/PartialRuntime_MM", "formalisms/SimpleClassDiagrams", open("models/DTCBD/metamodels/DTCBD_MM_partial_runtime.mvc", 'r').read())
+model_add("formalisms/DTCBD/FullRuntime_MM", "formalisms/SimpleClassDiagrams", open("models/DTCBD/metamodels/DTCBD_MM_runtime.mvc", 'r').read())
+
+model_add("models/DTCBD_model", "formalisms/DTCBD/Design_MM", open("models/DTCBD/models/simple_equation.mvc", 'r').read())
+
+transformation_add_MANUAL({"Design": "formalisms/DTCBD/Design_MM"}, {"Design": "formalisms/DTCBD/Design_MM"}, "models/DTCBD/edit")
+
+def trace_D2P(model):
+    instantiate(model, "Association", ("Design/Block", "PartialRuntime/Block"), ID="D2P_block")
+
+transformation_add_AL({"Design": "formalisms/DTCBD/Design_MM", "PartialRuntime": "formalisms/DTCBD/PartialRuntime_MM"}, {"PartialRuntime": "formalisms/DTCBD/PartialRuntime_MM"}, "models/DTCBD/toRuntime", open("models/DTCBD/transformations/to_runtime.alc", 'r').read(), trace_D2P)
+
+def trace_P2F(model):
+    instantiate(model, "Association", ("PartialRuntime/Block", "FullRuntime/Block"), ID="P2F_block")
+
+transformation_add_AL({"PartialRuntime": "formalisms/DTCBD/PartialRuntime_MM", "FullRuntime": "formalisms/DTCBD/FullRuntime_MM"}, {"NewFullRuntime": "formalisms/DTCBD/FullRuntime_MM"}, "models/DTCBD/merge", open("models/DTCBD/transformations/merge.alc", 'r').read(), trace_P2F)
+transformation_add_AL({"FullRuntime": "formalisms/DTCBD/FullRuntime_MM"}, {"FullRuntime": "formalisms/DTCBD/FullRuntime_MM"}, "models/DTCBD/simulate", open("models/DTCBD/transformations/simulate.alc", 'r').read())
+transformation_add_AL({}, {}, "models/DTCBD/restartSim", open("models/generic/restart_simulation.alc", 'r').read())
+
+model_add("models/live_modelling_DTCBD", "formalisms/ProcessModel", open("models/DTCBD/PM_live_modelling.mvc", 'r').read())
+
+def modify_model(model):
+    elements = element_list_nice(model)
+    for e in elements:
+        if e.get("value", None) == 2.0:
+            while 1:
+                time.sleep(1)
+        elif e.get("type", None) == "Design/AdditionBlock":
+            adder = e["id"]
+            links = read_outgoing(model, adder, "Design/Link")
+            destinations = [read_association_destination(model, link) for link in links]
+    else:
+        mult = instantiate(model, "Design/MultiplyBlock")
+        two = instantiate(model, "Design/ConstantBlock")
+        attr_assign(model, two, "value", 2.0)
+        instantiate(model, "Design/Link", (adder, mult))
+        instantiate(model, "Design/Link", (two, mult))
+        for link in links:
+            delete_element(model, link)
+        for destination in destinations:
+            instantiate(model, "Design/Link", (mult, destination))
+
+process_execute("models/live_modelling_DTCBD", {"design_model": "models/DTCBD_model"}, {"models/DTCBD/edit": modify_model})

+ 48 - 0
examples/live_modelling_FSA.py

@@ -0,0 +1,48 @@
+import sys
+sys.path.append("wrappers")
+from modelverse import *
+
+init()
+login("admin", "admin")
+
+### live modelling FSA
+
+model_add("formalisms/FSA/Design_MM", "formalisms/SimpleClassDiagrams", open("models/FiniteStateAutomata/metamodels/FSA_MM.mvc", 'r').read())
+model_add("formalisms/FSA/PartialRuntime_MM", "formalisms/SimpleClassDiagrams", open("models/FiniteStateAutomata/metamodels/FSA_MM_partial_runtime.mvc", 'r').read())
+model_add("formalisms/FSA/FullRuntime_MM", "formalisms/SimpleClassDiagrams", open("models/FiniteStateAutomata/metamodels/FSA_MM_runtime.mvc", 'r').read())
+
+model_add("models/FSA_model", "formalisms/FSA/Design_MM", open("models/FiniteStateAutomata/models/alarm.mvc", 'r').read())
+
+transformation_add_MANUAL({"Design": "formalisms/FSA/Design_MM"}, {"Design": "formalisms/FSA/Design_MM"}, "models/FSA/edit")
+
+def trace_D2P(model):
+    instantiate(model, "Association", ("Design/State", "PartialRuntime/State"), ID="D2P_state")
+
+transformation_add_AL({"Design": "formalisms/FSA/Design_MM", "PartialRuntime": "formalisms/FSA/PartialRuntime_MM"}, {"PartialRuntime": "formalisms/FSA/PartialRuntime_MM"}, "models/FSA/toRuntime", open("models/FiniteStateAutomata/transformations/to_runtime.alc", 'r').read(), trace_D2P)
+
+def trace_P2F(model):
+    instantiate(model, "Association", ("PartialRuntime/State", "FullRuntime/State"), ID="P2F_state")
+
+transformation_add_AL({"PartialRuntime": "formalisms/FSA/PartialRuntime_MM", "FullRuntime": "formalisms/FSA/FullRuntime_MM"}, {"NewFullRuntime": "formalisms/FSA/FullRuntime_MM"}, "models/FSA/merge", open("models/FiniteStateAutomata/transformations/merge.alc", 'r').read(), trace_P2F)
+transformation_add_AL({"FullRuntime": "formalisms/FSA/FullRuntime_MM"}, {"FullRuntime": "formalisms/FSA/FullRuntime_MM"}, "models/FSA/simulate", open("models/FiniteStateAutomata/transformations/simulate.alc", 'r').read())
+transformation_add_AL({}, {}, "models/FSA/restartSim", open("models/generic/restart_simulation.alc", 'r').read())
+
+model_add("models/live_modelling_FSA", "formalisms/ProcessModel", open("models/FiniteStateAutomata/PM_live_modelling.mvc", 'r').read())
+
+def edit_FSA(model):
+    elements = element_list_nice(model)
+    for e in elements:
+        if e.get("name", None) == "idle":
+            delete_element(model, e["id"])
+            break
+    else:
+        while 1:
+            time.sleep(1)
+
+    # Removed, so set a new element as initial
+    for e in elements:
+        if e.get("name", None) == "armed":
+            attr_assign(model, e["id"], "initial", True)
+            break
+
+process_execute("models/live_modelling_FSA", {"design_model": "models/FSA_model"}, {"models/FSA/edit": modify_model})

+ 27 - 0
examples/pm_simulation.py

@@ -0,0 +1,27 @@
+import sys
+sys.path.append("wrappers/")
+
+from modelverse import *
+
+init()
+login("admin", "admin")
+
+model_add("formalisms/DEVS/DEVS_MM", "formalisms/SimpleClassDiagrams", open("models/ClassicDEVS/metamodels/DEVS.mvc", 'r').read())
+model_add("formalisms/PM/PM_Extended_MM", "formalisms/SimpleClassDiagrams", open("models/FTGPM/metamodels/control_patterns.mvc", 'r').read())
+model_add("formalisms/Experiment/Experiment_MM", "formalisms/SimpleClassDiagrams", open("models/PythonPDEVS_Experiment/metamodels/experiment.mvc", 'r').read())
+
+model_add("models/PM/to_DEVS", "formalisms/ProcessModel", open("models/FTGPM/PM_patterns_simulation.mvc").read())
+
+model_add("models/DEVS/PM_library", "formalisms/DEVS/DEVS_MM", open("models/ClassicDEVS/models/process_patterns_library.mvc", 'r').read())
+model_add("models/PM/example_PM", "formalisms/PM/PM_Extended_MM", open("models/FTGPM/models/example_patterns.mvc", 'r').read())
+model_add("models/Experiment/example_experiment", "formalisms/Experiment/Experiment_MM", open("models/PythonPDEVS_Experiment/models/optimize_PM_resources.mvc", 'r').read())
+
+def traceability_pm_devs(model):
+    instantiate(model, "Association", ("PM/ProcessNode", "DEVS/DEVSInstance"), ID="Trace")
+
+transformation_add_MT({"PM": "formalisms/PM/PM_Extended_MM"}, {"DEVS": "formalisms/DEVS/DEVS_MM"}, "formalisms/PM/to_DEVS", open("models/FTGPM/transformations/patterns_to_DEVS.mvc", 'r').read(), traceability_pm_devs)
+
+transformation_add_AL({"model1": "formalisms/DEVS/DEVS_MM", "model2": "formalisms/DEVS/DEVS_MM"}, {"result": "formalisms/DEVS/DEVS_MM"}, "formalisms/DEVS/merge", open("models/ClassicDEVS/transformations/merge.alc", 'r').read())
+transformation_add_AL({"DEVS": "formalisms/DEVS/DEVS_MM", "Experiment": "formalisms/Experiment/Experiment_MM"}, {}, "formalisms/DEVS/simulate", open("models/ClassicDEVS/transformations/simulate.alc", 'r').read())
+
+process_execute("models/PM/to_DEVS", {"PM": "models/PM/example_PM", "DEVS library": "models/DEVS/PM_library", "Experiment": "models/Experiment/example_experiment"}, {})

+ 103 - 0
examples/powerwindow.py

@@ -0,0 +1,103 @@
+import shutil
+import sys
+import os
+sys.path.append("wrappers")
+from modelverse import *
+
+init()
+login("admin", "admin")
+
+model_add("formalisms/ReachabilityGraph", "formalisms/SimpleClassDiagrams", open("models/ReachabilityGraph/metamodels/reachability_graph.mvc", "r").read())
+model_add("formalisms/PetriNet", "formalisms/SimpleClassDiagrams", open("models/PetriNets/metamodels/PetriNets.mvc", 'r').read())
+model_add("formalisms/Encapsulated_PetriNet", "formalisms/SimpleClassDiagrams", open("models/EncapsulatedPetriNets/metamodels/epn.mvc", 'r').read())
+model_add("formalisms/PW_Plant", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/plant.mvc", 'r').read())
+model_add("formalisms/PW_Environment", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/environment.mvc", 'r').read())
+model_add("formalisms/PW_Control", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/control.mvc", 'r').read())
+model_add("formalisms/Requirements", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/requirements.mvc", 'r').read())
+model_add("formalisms/Query", "formalisms/SimpleClassDiagrams", open("models/SafetyQuery/metamodels/query.mvc", 'r').read())
+model_add("formalisms/Architecture", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/architecture.mvc", 'r').read())
+
+model_add("models/pm_powerwindow", "formalisms/ProcessModel", open("models/PowerWindow/PM_analyze.mvc", 'r').read())
+
+transformation_add_MANUAL({"Requirements": "formalisms/Requirements"}, {"Requirements": "formalisms/Requirements"}, "models/revise_req")
+transformation_add_MANUAL({"Requirements": "formalisms/Requirements", "PW_Environment": "formalisms/PW_Environment"}, {"PW_Environment": "formalisms/PW_Environment"}, "models/revise_environment")
+transformation_add_MANUAL({"Requirements": "formalisms/Requirements", "PW_Plant": "formalisms/PW_Plant"}, {"PW_Plant": "formalisms/PW_Plant"}, "models/revise_plant")
+transformation_add_MANUAL({"Requirements": "formalisms/Requirements", "PW_Control": "formalisms/PW_Control"}, {"PW_Control": "formalisms/PW_Control"}, "models/revise_control")
+transformation_add_MANUAL({"Requirements": "formalisms/Requirements", "Query": "formalisms/Query"}, {"Query": "formalisms/Query"}, "models/revise_query")
+transformation_add_MANUAL({"Requirements": "formalisms/Requirements", "Architecture": "formalisms/Architecture"}, {"Architecture": "formalisms/Architecture"}, "models/revise_architecture")
+
+def tracability_CTRL2EPN(model):
+    instantiate(model, "Association", ("PW_Control/State", "Encapsulated_PetriNet/Place"), ID="CTRL2EPN_link")
+    instantiate(model, "Association", ("PW_Control/Transition", "Encapsulated_PetriNet/Transition"), ID="CTRL2EPN_tlink")
+
+def tracability_PLANT2EPN(model):
+    instantiate(model, "Association", ("PW_Plant/State", "Encapsulated_PetriNet/Place"), ID="PLANT2EPN_link")
+    instantiate(model, "Association", ("PW_Plant/Transition", "Encapsulated_PetriNet/Transition"), ID="PLANT2EPN_tlink")
+
+def tracability_ENV2EPN(model):
+    instantiate(model, "Association", ("PW_Environment/Event", "Encapsulated_PetriNet/Place"), ID="ENV2EPN_link")
+
+def tracability_EPN2PN(model):
+    instantiate(model, "Association", ("Encapsulated_PetriNet/Place", "PetriNet/Place"), ID="EPN2PN_transition_link")
+    instantiate(model, "Association", ("Encapsulated_PetriNet/Transition", "PetriNet/Transition"), ID="EPN2PN_place_link")
+
+transformation_add_MT({}, {"PW_Plant": "formalisms/PW_Plant", "PW_Environment": "formalisms/PW_Environment", "PW_Control": "formalisms/PW_Control", "Query": "formalisms/Query", "Architecture": "formalisms/Architecture", "Requirements": "formalisms/Requirements"}, "models/make_initial_models", open("models/PowerWindow/transformations/initialize.mvc", 'r').read())
+transformation_add_MT({"PW_Plant": "formalisms/PW_Plant"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/plant_to_EPN", open("models/PowerWindow/transformations/plant_to_EPN.mvc", 'r').read(), tracability_PLANT2EPN)
+transformation_add_MT({"PW_Control": "formalisms/PW_Control"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/control_to_EPN", open("models/PowerWindow/transformations/control_to_EPN.mvc", 'r').read(), tracability_CTRL2EPN)
+transformation_add_MT({"PW_Environment": "formalisms/PW_Environment"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/environment_to_EPN", open("models/PowerWindow/transformations/environment_to_EPN.mvc", 'r').read(), tracability_ENV2EPN)
+transformation_add_MT({"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet", "Architecture": "formalisms/Architecture"}, {"PetriNet": "formalisms/PetriNet"}, "models/combine_EPN", open("models/EncapsulatedPetriNets/transformations/combine.mvc", 'r').read(), tracability_EPN2PN)
+transformation_add_MT({"ReachabilityGraph": "formalisms/ReachabilityGraph", "Query": "formalisms/Query"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/match", open("models/ReachabilityGraph/transformations/match_query.mvc", 'r').read())
+
+transformation_add_AL({"PetriNet": "formalisms/PetriNet"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/reachability", open("models/PetriNets/transformations/reachability.alc", 'r').read())
+transformation_add_AL({"ReachabilityGraph": "formalisms/ReachabilityGraph"}, {}, "models/bfs", open("models/ReachabilityGraph/transformations/bfs.alc", 'r').read())
+transformation_add_AL({"EPN_Plant": "formalisms/Encapsulated_PetriNet", "EPN_Control": "formalisms/Encapsulated_PetriNet", "EPN_Environment": "formalisms/Encapsulated_PetriNet"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/merge_EPN", open("models/EncapsulatedPetriNets/transformations/merge.alc", 'r').read())
+
+nr_of_operations = 6
+
+try:
+    shutil.rmtree(".TEST_POWER_WINDOW")
+except:
+    pass
+os.makedirs(".TEST_POWER_WINDOW")
+
+def get_function(filename):
+    def func(model):
+        import uuid
+        import os
+        called = len(os.listdir(".TEST_POWER_WINDOW/"))
+        if called > nr_of_operations:
+            raise Exception("Seemingly called some operation twice!")
+        else:
+            f = open(".TEST_POWER_WINDOW/%s" % str(uuid.uuid4()), 'w')
+            f.write(filename)
+            f.close()
+        model_overwrite(model, open(filename, "r").read())
+    return func
+
+cb_req = get_function(  "models/PowerWindow/models/requirements.mvc")
+cb_plant = get_function("models/PowerWindow/models/plant.mvc")
+cb_env = get_function(  "models/PowerWindow/models/environment.mvc")
+cb_ctrl = get_function( "models/PowerWindow/models/control.mvc")
+cb_query = get_function("models/SafetyQuery/models/powerwindow_safe.mvc")
+cb_arch = get_function( "models/PowerWindow/models/architecture.mvc")
+
+callbacks = {
+        "models/revise_req": cb_req,
+        "models/revise_plant": cb_plant,
+        "models/revise_environment": cb_env,
+        "models/revise_control": cb_ctrl,
+        "models/revise_query": cb_query,
+        "models/revise_architecture": cb_arch,
+    }
+
+try:
+    process_execute("models/pm_powerwindow", {}, callbacks)
+except:
+    import traceback
+    print(traceback.format_exc())
+
+called = len(os.listdir(".TEST_POWER_WINDOW/"))
+shutil.rmtree(".TEST_POWER_WINDOW")
+if called != 6:
+    print(called)
+    raise Exception("Not executed sufficiently:" + str(called))

+ 18 - 0
examples/render_DTCBD_graphical.py

@@ -0,0 +1,18 @@
+import sys
+sys.path.append("wrappers")
+from modelverse import *
+
+init()
+login("admin", "admin")
+
+model_add("formalisms/DTCBD/Design_MM", "formalisms/SimpleClassDiagrams", open("models/DTCBD/metamodels/DTCBD_MM.mvc", 'r').read())
+model_add("models/DTCBD_model", "formalisms/DTCBD/Design_MM", open("models/DTCBD/models/simple_equation.mvc", 'r').read())
+
+model_add("formalisms/MM_render/graphical", "formalisms/SimpleClassDiagrams", open("models/render/metamodels/graphical.mvc", 'r').read())
+
+def add_trace_CBD(model):
+    instantiate(model, "Association", ("abstract/Block", "rendered/Group"), ID="TracabilityClass")
+
+transformation_add_AL({"abstract": "formalisms/DTCBD/Design_MM", "rendered": "formalisms/MM_render/graphical"}, {"rendered": "formalisms/MM_render/graphical"}, "models/DTCBD/render_graphical", open("models/DTCBD/transformations/render.alc", 'r').read(), add_trace_CBD)
+
+print(model_render("models/DTCBD_model", "models/DTCBD/render_graphical", "perceptualized/DTCBD_model"))

+ 18 - 0
examples/render_DTCBD_plot.py

@@ -0,0 +1,18 @@
+import sys
+sys.path.append("wrappers")
+from modelverse import *
+
+init()
+login("admin", "admin")
+
+model_add("formalisms/Trace", "formalisms/SimpleClassDiagrams", open("models/Signal/metamodels/trace.mvc", 'r').read())
+model_add("models/trace", "formalisms/Trace", open("models/Signal/models/spring.mvc", 'r').read())
+
+model_add("formalisms/MM_render/plot", "formalisms/SimpleClassDiagrams", open("models/render/metamodels/plot.mvc", 'r').read())
+
+def add_trace_trace(model):
+    instantiate(model, "Association", ("abstract/Signal", "rendered/Dataset"), ID="TracabilityLink")
+
+transformation_add_MT({"abstract": "formalisms/Trace", "rendered": "formalisms/MM_render/plot"}, {"rendered": "formalisms/MM_render/plot"}, "models/trace_mapper", open("models/Signal/transformations/render.mvc", 'r').read(), add_trace_trace)
+
+print(model_render("models/trace", "models/trace_mapper", "perceptualized/Trace_model"))

+ 10 - 49
hybrid_server/classes/mvkcontroller.xml

@@ -10,7 +10,7 @@
             <![CDATA[
             self.mvs = ModelverseState("../bootstrap/bootstrap.m.gz")
             # Enable Garbage Collection
-            self.mvs.GC = True
+            self.mvs.GC = False
 
             self.root = self.mvs.read_root()
 
@@ -24,53 +24,7 @@
                 if parameter.startswith('--kernel='):
                     kernel_opts = parameter[len('--kernel='):].split(',')
 
-            for opt in kernel_opts:
-                if opt == 'legacy-interpreter':
-                    self.mvk = LegacyModelverseKernel(self.root)
-                elif opt == 'generated':
-                    self.mvk = GeneratedModelverseKernel(self.root)
-                elif opt == 'interpreter':
-                    self.mvk.jit.set_jit_enabled(False)
-                elif opt == 'no-thunks':
-                    self.mvk.jit.enable_thunks(False)
-                elif opt == 'thunks':
-                    self.mvk.jit.enable_thunks()
-                elif opt == 'no-source-maps':
-                    self.mvk.jit.enable_source_maps(False)
-                elif opt == 'source-maps':
-                    self.mvk.jit.enable_source_maps()
-                elif opt == 'no-insert-nops':
-                    self.mvk.jit.enable_nop_insertion(False)
-                elif opt == 'insert-nops':
-                    self.mvk.jit.enable_nop_insertion()
-                elif opt == 'trace':
-                    self.mvk.jit.enable_tracing()
-                elif opt == 'bytecode-interpreter':
-                    self.mvk.jit.set_function_body_compiler(jit.compile_function_body_interpret)
-                elif opt == 'baseline-jit':
-                    self.mvk.jit.set_function_body_compiler(jit.compile_function_body_baseline)
-                elif opt == 'fast-jit':
-                    self.mvk.jit.set_function_body_compiler(jit.compile_function_body_fast)
-                elif opt == 'adaptive-jit-favor-large-functions':
-                    self.mvk.jit.set_function_body_compiler(
-                            lambda *args: jit.compile_function_body_adaptive(
-                                *args, temperature_heuristic=jit.favor_large_functions))
-                elif opt == 'adaptive-jit-favor-small-functions':
-                    self.mvk.jit.set_function_body_compiler(
-                        lambda *args: jit.compile_function_body_adaptive(
-                            *args, temperature_heuristic=jit.favor_small_functions))
-                elif opt == 'adaptive-jit-favor-loops':
-                    self.mvk.jit.set_function_body_compiler(
-                        lambda *args: jit.compile_function_body_adaptive(
-                            *args, temperature_heuristic=jit.favor_loops))
-                elif opt == 'adaptive-jit' or opt == 'adaptive-jit-favor-small-loops':
-                    self.mvk.jit.set_function_body_compiler(
-                        lambda *args: jit.compile_function_body_adaptive(
-                            *args, temperature_heuristic=jit.favor_small_loops))
-                else:
-                    print("warning: unknown kernel option '%s'." % opt)
-
-            self.port = int(sys.argv[1])
+            self.port = int(params[0])
 
             self.sc_map = {}
             self.forward = None
@@ -356,11 +310,18 @@
                     <state id="mvs_GC">
                         <onentry>
                             <script>
+                                print("Modelverse Garbage Collection")
+                                self.execute_modelverse("", "protect_temporary_variables", [])
                                 self.mvs.purge()
+                                self.execute_modelverse("", "unprotect_temporary_variables", [])
+
+                                # Clean up all used memory now, as this is rather much due to the copy of the MvS
+                                import gc
+                                gc.collect()
                             </script>
                             <raise scope="broad" event="resume_task"/>
                         </onentry>
-                        <transition after="self.sccd_yield() + 10" target="."/>
+                        <transition after="self.sccd_yield() + 600" target="."/>
                     </state>
                 </state>
             </parallel>

+ 1 - 0
hybrid_server/classes/socket.xml

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

+ 11 - 0
hybrid_server/classes/task.xml

@@ -40,8 +40,19 @@
                 return (0.0, False)
             except SleepKernel as e:
                 return (e.timeout, e.interruptable)
+            except KeyboardInterrupt:
+                raise
             except:
                 import traceback
+                print("Error on requests: " + str(commands))
+                print("For taskname " + str(taskname))
+                stack = [gen for gen in mvk.request_handlers[taskname][operation].generator_stack if gen is not None and gen.__name__ not in ['execute_rule', 'execute_jit']]
+                printed_stack = []
+                for gen in stack:
+                    line = getattr(getattr(gen, "gi_frame", {}), "f_lineno", "?")
+                    variables = getattr(getattr(gen, "gi_frame", {}), "f_locals", "?")
+                    printed_stack.append("%s:%s {%s}" % (gen.__name__, line, variables))
+                print("Stack @ MvK:\n" + str("\n".join(printed_stack)))
                 print(traceback.format_exc())
                 return (float('inf'), False)
             ]]>

+ 0 - 3
hybrid_server/server.xml

@@ -23,11 +23,8 @@
         sys.path.append("../state/")
         from modelverse_kernel.primitives import SleepKernel
         from modelverse_kernel.main import ModelverseKernel
-        from modelverse_kernel.legacy import ModelverseKernel as LegacyModelverseKernel
-        from modelverse_kernel.generated import ModelverseKernel as GeneratedModelverseKernel
         from modelverse_state.main import ModelverseState
         #from modelverse_state.rdf import ModelverseState
-        import modelverse_jit.jit as jit
     </top>
 
     <inport name="socket_in"/>

+ 102 - 0
hybrid_server/stacktracer.py

@@ -0,0 +1,102 @@
+"""Stack tracer for multi-threaded applications.
+
+
+Usage:
+
+import stacktracer
+stacktracer.trace_start("trace.html",interval=5,auto=True) # Set auto flag to always update file!
+....
+stacktracer.stop_trace()
+"""
+
+
+
+import sys
+import traceback
+from pygments import highlight
+from pygments.lexers import PythonLexer
+from pygments.formatters import HtmlFormatter
+ 
+ # Taken from http://bzimmer.ziclix.com/2008/12/17/python-thread-dumps/
+ 
+def stacktraces():
+    code = []
+    for threadId, stack in sys._current_frames().items():
+        code.append("\n# ThreadID: %s" % threadId)
+        for filename, lineno, name, line in traceback.extract_stack(stack):
+            code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
+            if line:
+                code.append("  %s" % (line.strip()))
+ 
+    return highlight("\n".join(code), PythonLexer(), HtmlFormatter(
+      full=False,
+      # style="native",
+      noclasses=True,
+    ))
+
+
+# This part was made by nagylzs
+import os
+import time
+import threading
+
+class TraceDumper(threading.Thread):
+    """Dump stack traces into a given file periodically."""
+    def __init__(self,fpath,interval,auto):
+        """
+        @param fpath: File path to output HTML (stack trace file)
+        @param auto: Set flag (True) to update trace continuously.
+            Clear flag (False) to update only if file not exists.
+            (Then delete the file to force update.)
+        @param interval: In seconds: how often to update the trace file.
+        """
+        assert(interval>0.1)
+        self.auto = auto
+        self.interval = interval
+        self.fpath = os.path.abspath(fpath)
+        self.stop_requested = threading.Event()
+        threading.Thread.__init__(self)
+    
+    def run(self):
+        while not self.stop_requested.isSet():
+            time.sleep(self.interval)
+            if self.auto or not os.path.isfile(self.fpath):
+                self.stacktraces()
+    
+    def stop(self):
+        self.stop_requested.set()
+        self.join()
+        try:
+            if os.path.isfile(self.fpath):
+                os.unlink(self.fpath)
+        except:
+            pass
+    
+    def stacktraces(self):
+        fout = open(self.fpath,"wb+")
+        try:
+            fout.write(stacktraces())
+        finally:
+            fout.close()
+
+
+_tracer = None
+def trace_start(fpath,interval=5,auto=True):
+    """Start tracing into the given file."""
+    global _tracer
+    if _tracer is None:
+        _tracer = TraceDumper(fpath,interval,auto)
+        _tracer.setDaemon(True)
+        _tracer.start()
+    else:
+        return
+        #raise Exception("Already tracing to %s"%_tracer.fpath)
+
+def trace_stop():
+    """Stop tracing."""
+    global _tracer
+    if _tracer is None:
+        raise Exception("Not tracing, cannot stop.")
+    else:
+        _tracer.stop()
+        _tracer = None

models/CBD_mapper.mvc → integration/code/CBD_mapper.mvc


models/MM_rendered_graphical.mvc → integration/code/MM_rendered_graphical.mvc


models/SCCD.mvc → integration/code/SCCD.mvc


models/SCCD_Trace.mvc → integration/code/SCCD_Trace.mvc


+ 15 - 15
integration/code/SCCD_all.mvc

@@ -110,7 +110,7 @@ transition (manager_main_parallel_input_1, manager_main_parallel_input_2) {
         scope = "broad"
         event = "create"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -127,7 +127,7 @@ transition (manager_main_parallel_input_2, manager_main_parallel_input_3) {
         scope = "broad"
         event = "toggle"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -144,7 +144,7 @@ transition (manager_main_parallel_input_3, manager_main_parallel_input_4) {
         scope = "broad"
         event = "create"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -161,7 +161,7 @@ transition (manager_main_parallel_input_4, manager_main_parallel_input_5) {
         scope = "broad"
         event = "police_interrupt"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -178,7 +178,7 @@ transition (manager_main_parallel_input_5, manager_main_parallel_input_6) {
         scope = "broad"
         event = "toggle"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -195,7 +195,7 @@ transition (manager_main_parallel_input_6, manager_main_parallel_input_7) {
         scope = "broad"
         event = "toggle"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -212,7 +212,7 @@ transition (manager_main_parallel_input_7, manager_main_parallel_input_8) {
         scope = "broad"
         event = "police_interrupt"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -229,7 +229,7 @@ transition (manager_main_parallel_input_8, manager_main_parallel_input_9) {
         scope = "broad"
         event = "delete"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -246,7 +246,7 @@ transition (manager_main_parallel_input_9, manager_main_parallel_input_10) {
         scope = "broad"
         event = "delete"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -263,7 +263,7 @@ transition (manager_main_parallel_input_10, manager_main_parallel_input_11) {
         scope = "broad"
         event = "exit"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     return list_create()!
             $
     }
@@ -277,7 +277,7 @@ transition (manager_main_parallel_core_start, manager_main_parallel_core_start)
         scope = "cd"
         event = "create_instance"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     Element result
                     result = list_create()
                     list_append(result, "trafficlights")
@@ -307,7 +307,7 @@ transition (manager_main_parallel_core_start, manager_main_parallel_core_start)
         scope = "cd"
         event = "delete_instance"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     Element result
                     result = list_create()
                     list_append(result, "0")
@@ -324,7 +324,7 @@ transition (manager_main_parallel_core_start, manager_main_parallel_core_start)
         scope = "cd"
         event = "delete_instance"
         parameter = $
-                Element function raise(attributes : Element, parameters : Element):
+                Element function raises(attributes : Element, parameters : Element):
                     Element result
                     result = list_create()
                     list_append(result, list_pop_final(attributes["trafficlights"]))
@@ -499,7 +499,7 @@ Class trafficlight {
                             event = "updateTimerValue"
                             scope = "output"
                             parameter = $
-                                    Element function raise(attributes : Element):
+                                    Element function raises(attributes : Element):
                                         return attributes["counter"]!
                                 $
                         }
@@ -512,7 +512,7 @@ Class trafficlight {
                         {onEntryRaise} Raise {
                             event = "updateTimerValue"
                             parameter = $
-                                    Element function raise(attributes : Element):
+                                    Element function raises(attributes : Element):
                                         return attributes["counter"]!
                                 $
                         }

+ 1 - 0
models/SCCD_execute.alc

@@ -128,6 +128,7 @@ Element function expand_parallel_state(model : Element, parallel_state : String,
 Void function delete_class(model : Element, data : Element, identifier : String):
 	// Stop a specific class instance, with attached statechart, from executing
 	dict_delete(data["classes"], identifier)
+	return!
 
 String function start_class(model : Element, data : Element, class : String, parameters : Element):
 	// Start up the class and assign its initial state to it

+ 60 - 163
integration/test_powerwindow.py

@@ -19,17 +19,17 @@ class TestPowerWindow(unittest.TestCase):
         kill(self.proc)
 
     def test_process_powerwindow_fast(self):
-        model_add("formalisms/ReachabilityGraph", "formalisms/SimpleClassDiagrams", open("models/reachability_graph.mvc", "r").read())
-        model_add("formalisms/PetriNet", "formalisms/SimpleClassDiagrams", open("integration/code/pn_design.mvc", 'r').read())
-        model_add("formalisms/Encapsulated_PetriNet", "formalisms/SimpleClassDiagrams", open("models/petrinet_ports.mvc", 'r').read())
-        model_add("formalisms/PW_Plant", "formalisms/SimpleClassDiagrams", open("models/plant_PW.mvc", 'r').read())
-        model_add("formalisms/PW_Environment", "formalisms/SimpleClassDiagrams", open("models/environment_PW.mvc", 'r').read())
-        model_add("formalisms/PW_Control", "formalisms/SimpleClassDiagrams", open("models/control_PW.mvc", 'r').read())
-        model_add("formalisms/Requirements", "formalisms/SimpleClassDiagrams", open("models/requirements.mvc", 'r').read())
-        model_add("formalisms/Query", "formalisms/SimpleClassDiagrams", open("models/query.mvc", 'r').read())
-        model_add("formalisms/Architecture", "formalisms/SimpleClassDiagrams", open("models/architecture.mvc", 'r').read())
-
-        model_add("models/pm_powerwindow", "formalisms/ProcessModel", open("models/pm_req_analyse.mvc", 'r').read())
+        model_add("formalisms/ReachabilityGraph", "formalisms/SimpleClassDiagrams", open("models/ReachabilityGraph/metamodels/reachability_graph.mvc", "r").read())
+        model_add("formalisms/PetriNet", "formalisms/SimpleClassDiagrams", open("models/PetriNets/metamodels/PetriNets.mvc", 'r').read())
+        model_add("formalisms/Encapsulated_PetriNet", "formalisms/SimpleClassDiagrams", open("models/EncapsulatedPetriNets/metamodels/epn.mvc", 'r').read())
+        model_add("formalisms/PW_Plant", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/plant.mvc", 'r').read())
+        model_add("formalisms/PW_Environment", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/environment.mvc", 'r').read())
+        model_add("formalisms/PW_Control", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/control.mvc", 'r').read())
+        model_add("formalisms/Requirements", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/requirements.mvc", 'r').read())
+        model_add("formalisms/Query", "formalisms/SimpleClassDiagrams", open("models/SafetyQuery/metamodels/query.mvc", 'r').read())
+        model_add("formalisms/Architecture", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/architecture.mvc", 'r').read())
+
+        model_add("models/pm_powerwindow", "formalisms/ProcessModel", open("models/PowerWindow/PM_analyze.mvc", 'r').read())
 
         transformation_add_MANUAL({"Requirements": "formalisms/Requirements"}, {"Requirements": "formalisms/Requirements"}, "models/revise_req")
         transformation_add_MANUAL({"Requirements": "formalisms/Requirements", "PW_Environment": "formalisms/PW_Environment"}, {"PW_Environment": "formalisms/PW_Environment"}, "models/revise_environment")
@@ -53,16 +53,16 @@ class TestPowerWindow(unittest.TestCase):
             instantiate(model, "Association", ("Encapsulated_PetriNet/Place", "PetriNet/Place"), ID="EPN2PN_transition_link")
             instantiate(model, "Association", ("Encapsulated_PetriNet/Transition", "PetriNet/Transition"), ID="EPN2PN_place_link")
 
-        transformation_add_MT({}, {"PW_Plant": "formalisms/PW_Plant", "PW_Environment": "formalisms/PW_Environment", "PW_Control": "formalisms/PW_Control", "Query": "formalisms/Query", "Architecture": "formalisms/Architecture", "Requirements": "formalisms/Requirements"}, "models/make_initial_models", open("models/initialize.mvc", 'r').read())
-        transformation_add_MT({"PW_Plant": "formalisms/PW_Plant"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/plant_to_EPN", open("models/plant_to_EPN.mvc", 'r').read(), tracability_PLANT2EPN)
-        transformation_add_MT({"PW_Control": "formalisms/PW_Control"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/control_to_EPN", open("models/control_to_EPN.mvc", 'r').read(), tracability_CTRL2EPN)
-        transformation_add_MT({"PW_Environment": "formalisms/PW_Environment"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/environment_to_EPN", open("models/environment_to_EPN.mvc", 'r').read(), tracability_ENV2EPN)
-        transformation_add_MT({"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet", "Architecture": "formalisms/Architecture"}, {"PetriNet": "formalisms/PetriNet"}, "models/combine_EPN", open("models/combine_EPN.mvc", 'r').read(), tracability_EPN2PN)
-        transformation_add_MT({"ReachabilityGraph": "formalisms/ReachabilityGraph", "Query": "formalisms/Query"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/match", open("models/matches.mvc", 'r').read())
+        transformation_add_MT({}, {"PW_Plant": "formalisms/PW_Plant", "PW_Environment": "formalisms/PW_Environment", "PW_Control": "formalisms/PW_Control", "Query": "formalisms/Query", "Architecture": "formalisms/Architecture", "Requirements": "formalisms/Requirements"}, "models/make_initial_models", open("models/PowerWindow/transformations/initialize.mvc", 'r').read())
+        transformation_add_MT({"PW_Plant": "formalisms/PW_Plant"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/plant_to_EPN", open("models/PowerWindow/transformations/plant_to_EPN.mvc", 'r').read(), tracability_PLANT2EPN)
+        transformation_add_MT({"PW_Control": "formalisms/PW_Control"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/control_to_EPN", open("models/PowerWindow/transformations/control_to_EPN.mvc", 'r').read(), tracability_CTRL2EPN)
+        transformation_add_MT({"PW_Environment": "formalisms/PW_Environment"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/environment_to_EPN", open("models/PowerWindow/transformations/environment_to_EPN.mvc", 'r').read(), tracability_ENV2EPN)
+        transformation_add_MT({"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet", "Architecture": "formalisms/Architecture"}, {"PetriNet": "formalisms/PetriNet"}, "models/combine_EPN", open("models/EncapsulatedPetriNets/transformations/combine.mvc", 'r').read(), tracability_EPN2PN)
+        transformation_add_MT({"ReachabilityGraph": "formalisms/ReachabilityGraph", "Query": "formalisms/Query"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/match", open("models/ReachabilityGraph/transformations/match_query.mvc", 'r').read())
 
-        transformation_add_AL({"PetriNet": "formalisms/PetriNet"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/reachability", open("models/reachability.alc", 'r').read())
-        transformation_add_AL({"ReachabilityGraph": "formalisms/ReachabilityGraph"}, {}, "models/bfs", open("models/bfs.alc", 'r').read())
-        transformation_add_AL({"EPN_Plant": "formalisms/Encapsulated_PetriNet", "EPN_Control": "formalisms/Encapsulated_PetriNet", "EPN_Environment": "formalisms/Encapsulated_PetriNet"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/merge_EPN", open("models/merge_EPN.alc", 'r').read())
+        transformation_add_AL({"PetriNet": "formalisms/PetriNet"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/reachability", open("models/PetriNets/transformations/reachability.alc", 'r').read())
+        transformation_add_AL({"ReachabilityGraph": "formalisms/ReachabilityGraph"}, {}, "models/bfs", open("models/ReachabilityGraph/transformations/bfs.alc", 'r').read())
+        transformation_add_AL({"EPN_Plant": "formalisms/Encapsulated_PetriNet", "EPN_Control": "formalisms/Encapsulated_PetriNet", "EPN_Environment": "formalisms/Encapsulated_PetriNet"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/merge_EPN", open("models/EncapsulatedPetriNets/transformations/merge.alc", 'r').read())
 
         nr_of_operations = 6
 
@@ -86,20 +86,20 @@ class TestPowerWindow(unittest.TestCase):
                 model_overwrite(model, open(filename, "r").read())
             return func
 
-        cb_req = get_function("models/requirements_model.mvc")
-        cb_plant = get_function("models/plant_model.mvc")
-        cb_env = get_function("models/environment_model.mvc")
-        cb_ctrl = get_function("models/control_model.mvc")
-        cb_query = get_function("models/query_model.mvc")
-        cb_arch = get_function("models/architecture_model.mvc")
+        cb_req = get_function(  "models/PowerWindow/models/requirements.mvc")
+        cb_plant = get_function("models/PowerWindow/models/plant.mvc")
+        cb_env = get_function(  "models/PowerWindow/models/environment.mvc")
+        cb_ctrl = get_function( "models/PowerWindow/models/control.mvc")
+        cb_query = get_function("models/SafetyQuery/models/powerwindow_safe.mvc")
+        cb_arch = get_function( "models/PowerWindow/models/architecture.mvc")
 
         callbacks = {
-                "models/revise_req": cb_req,
-                "models/revise_plant": cb_plant,
-                "models/revise_environment": cb_env,
-                "models/revise_control": cb_ctrl,
-                "models/revise_query": cb_query,
-                "models/revise_architecture": cb_arch,
+            "models/revise_req": cb_req,
+            "models/revise_plant": cb_plant,
+            "models/revise_environment": cb_env,
+            "models/revise_control": cb_ctrl,
+            "models/revise_query": cb_query,
+            "models/revise_architecture": cb_arch,
             }
 
         try:
@@ -108,6 +108,7 @@ class TestPowerWindow(unittest.TestCase):
             import traceback
             print(traceback.format_exc())
 
+
         called = len(os.listdir(".TEST_POWER_WINDOW/"))
         shutil.rmtree(".TEST_POWER_WINDOW")
         if called != 6:
@@ -116,18 +117,17 @@ class TestPowerWindow(unittest.TestCase):
 
     @slow
     def test_process_powerwindow_debug(self):
-        model_add("formalisms/ReachabilityGraph", "formalisms/SimpleClassDiagrams", open("models/reachability_graph.mvc", "r").read())
-        model_add("formalisms/PetriNet", "formalisms/SimpleClassDiagrams", open("integration/code/pn_design.mvc", 'r').read())
-        model_add("formalisms/Encapsulated_PetriNet", "formalisms/SimpleClassDiagrams", open("models/petrinet_ports.mvc", 'r').read())
-        model_add("formalisms/PW_Plant", "formalisms/SimpleClassDiagrams", open("models/plant_PW.mvc", 'r').read())
-        model_add("formalisms/PW_Environment", "formalisms/SimpleClassDiagrams", open("models/environment_PW.mvc", 'r').read())
-        model_add("formalisms/PW_Control", "formalisms/SimpleClassDiagrams", open("models/control_PW.mvc", 'r').read())
-        model_add("formalisms/Requirements", "formalisms/SimpleClassDiagrams", open("models/requirements.mvc", 'r').read())
-        model_add("formalisms/Query", "formalisms/SimpleClassDiagrams", open("models/query.mvc", 'r').read())
-        model_add("formalisms/Architecture", "formalisms/SimpleClassDiagrams", open("models/architecture.mvc", 'r').read())
-
-        #model_add("models/pm_powerwindow", "formalisms/ProcessModel", open("models/pm_req_analyse_debug.mvc", 'r').read())
-        model_add("models/pm_powerwindow", "formalisms/ProcessModel", open("models/pm_req_analyse.mvc", 'r').read())
+        model_add("formalisms/ReachabilityGraph", "formalisms/SimpleClassDiagrams", open("models/ReachabilityGraph/metamodels/reachability_graph.mvc", "r").read())
+        model_add("formalisms/PetriNet", "formalisms/SimpleClassDiagrams", open("models/PetriNets/metamodels/PetriNets.mvc", 'r').read())
+        model_add("formalisms/Encapsulated_PetriNet", "formalisms/SimpleClassDiagrams", open("models/EncapsulatedPetriNets/metamodels/epn.mvc", 'r').read())
+        model_add("formalisms/PW_Plant", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/plant.mvc", 'r').read())
+        model_add("formalisms/PW_Environment", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/environment.mvc", 'r').read())
+        model_add("formalisms/PW_Control", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/control.mvc", 'r').read())
+        model_add("formalisms/Requirements", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/requirements.mvc", 'r').read())
+        model_add("formalisms/Query", "formalisms/SimpleClassDiagrams", open("models/SafetyQuery/metamodels/query.mvc", 'r').read())
+        model_add("formalisms/Architecture", "formalisms/SimpleClassDiagrams", open("models/PowerWindow/metamodels/architecture.mvc", 'r').read())
+
+        model_add("models/pm_powerwindow", "formalisms/ProcessModel", open("models/PowerWindow/PM_analyze.mvc", 'r').read())
 
         transformation_add_MANUAL({"Requirements": "formalisms/Requirements"}, {"Requirements": "formalisms/Requirements"}, "models/revise_req")
         transformation_add_MANUAL({"Requirements": "formalisms/Requirements", "PW_Environment": "formalisms/PW_Environment"}, {"PW_Environment": "formalisms/PW_Environment"}, "models/revise_environment")
@@ -151,19 +151,16 @@ class TestPowerWindow(unittest.TestCase):
             instantiate(model, "Association", ("Encapsulated_PetriNet/Place", "PetriNet/Place"), ID="EPN2PN_transition_link")
             instantiate(model, "Association", ("Encapsulated_PetriNet/Transition", "PetriNet/Transition"), ID="EPN2PN_place_link")
 
-        transformation_add_MT({}, {"PW_Plant": "formalisms/PW_Plant", "PW_Environment": "formalisms/PW_Environment", "PW_Control": "formalisms/PW_Control", "Query": "formalisms/Query", "Architecture": "formalisms/Architecture", "Requirements": "formalisms/Requirements"}, "models/make_initial_models", open("models/initialize.mvc", 'r').read())
-        transformation_add_MT({"PW_Plant": "formalisms/PW_Plant"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/plant_to_EPN", open("models/plant_to_EPN.mvc", 'r').read(), tracability_PLANT2EPN)
-        transformation_add_MT({"PW_Control": "formalisms/PW_Control"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/control_to_EPN", open("models/control_to_EPN.mvc", 'r').read(), tracability_CTRL2EPN)
-        transformation_add_MT({"PW_Environment": "formalisms/PW_Environment"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/environment_to_EPN", open("models/environment_to_EPN.mvc", 'r').read(), tracability_ENV2EPN)
-        transformation_add_MT({"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet", "Architecture": "formalisms/Architecture"}, {"PetriNet": "formalisms/PetriNet"}, "models/combine_EPN", open("models/combine_EPN.mvc", 'r').read(), tracability_EPN2PN)
-        transformation_add_MT({"ReachabilityGraph": "formalisms/ReachabilityGraph", "Query": "formalisms/Query"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/match", open("models/matches.mvc", 'r').read())
-
-        transformation_add_AL({"PetriNet": "formalisms/PetriNet"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/reachability", open("models/reachability.alc", 'r').read())
-        transformation_add_AL({"ReachabilityGraph": "formalisms/ReachabilityGraph"}, {}, "models/bfs", open("models/bfs.alc", 'r').read())
-        transformation_add_AL({"EPN_Plant": "formalisms/Encapsulated_PetriNet", "EPN_Control": "formalisms/Encapsulated_PetriNet", "EPN_Environment": "formalisms/Encapsulated_PetriNet"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/merge_EPN", open("models/merge_EPN.alc", 'r').read())
+        transformation_add_MT({}, {"PW_Plant": "formalisms/PW_Plant", "PW_Environment": "formalisms/PW_Environment", "PW_Control": "formalisms/PW_Control", "Query": "formalisms/Query", "Architecture": "formalisms/Architecture", "Requirements": "formalisms/Requirements"}, "models/make_initial_models", open("models/PowerWindow/transformations/initialize.mvc", 'r').read())
+        transformation_add_MT({"PW_Plant": "formalisms/PW_Plant"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/plant_to_EPN", open("models/PowerWindow/transformations/plant_to_EPN.mvc", 'r').read(), tracability_PLANT2EPN)
+        transformation_add_MT({"PW_Control": "formalisms/PW_Control"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/control_to_EPN", open("models/PowerWindow/transformations/control_to_EPN.mvc", 'r').read(), tracability_CTRL2EPN)
+        transformation_add_MT({"PW_Environment": "formalisms/PW_Environment"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/environment_to_EPN", open("models/PowerWindow/transformations/environment_to_EPN.mvc", 'r').read(), tracability_ENV2EPN)
+        transformation_add_MT({"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet", "Architecture": "formalisms/Architecture"}, {"PetriNet": "formalisms/PetriNet"}, "models/combine_EPN", open("models/EncapsulatedPetriNets/transformations/combine.mvc", 'r').read(), tracability_EPN2PN)
+        transformation_add_MT({"ReachabilityGraph": "formalisms/ReachabilityGraph", "Query": "formalisms/Query"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/match", open("models/ReachabilityGraph/transformations/match_query.mvc", 'r').read())
 
-        #transformation_add_AL({"Encapsulated_PetriNet": "Encapsulated_PetriNet"}, {}, "epn_print", open("models/epn_print.alc").read())
-        #transformation_add_AL({"PetriNet": "PetriNet"}, {}, "pn_print", open("models/pn_print.alc").read())
+        transformation_add_AL({"PetriNet": "formalisms/PetriNet"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/reachability", open("models/PetriNets/transformations/reachability.alc", 'r').read())
+        transformation_add_AL({"ReachabilityGraph": "formalisms/ReachabilityGraph"}, {}, "models/bfs", open("models/ReachabilityGraph/transformations/bfs.alc", 'r').read())
+        transformation_add_AL({"EPN_Plant": "formalisms/Encapsulated_PetriNet", "EPN_Control": "formalisms/Encapsulated_PetriNet", "EPN_Environment": "formalisms/Encapsulated_PetriNet"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/merge_EPN", open("models/EncapsulatedPetriNets/transformations/merge.alc", 'r').read())
 
         try:
             shutil.rmtree(".TEST_POWER_WINDOW")
@@ -190,12 +187,13 @@ class TestPowerWindow(unittest.TestCase):
                 open(".TEST_POWER_WINDOW/%s_%s" % (filename.rsplit("/", 1)[-1], uuid.uuid4()), 'w').close()
             return func
 
-        cb_req = get_function("models/requirements_model.mvc")
-        cb_plant = get_function("models/plant_model.mvc")
-        cb_env = get_function("models/environment_model.mvc")
-        cb_ctrl = get_function("models/control_model_wrong.mvc", fixed="models/control_model.mvc")
-        cb_query = get_function("models/query_model.mvc")
-        cb_arch = get_function("models/architecture_model.mvc")
+        cb_req = get_function(  "models/PowerWindow/models/requirements.mvc")
+        cb_plant = get_function("models/PowerWindow/models/plant.mvc")
+        cb_env = get_function(  "models/PowerWindow/models/environment.mvc")
+        cb_ctrl = get_function( "models/PowerWindow/models/control_wrong.mvc", fixed="models/PowerWindow/models/control.mvc")
+        cb_query = get_function("models/SafetyQuery/models/powerwindow_safe.mvc")
+        cb_arch = get_function( "models/PowerWindow/models/architecture.mvc")
+
 
         import log_output
         error_path = []
@@ -226,104 +224,3 @@ class TestPowerWindow(unittest.TestCase):
             raise Exception("Not executed sufficiently:" + str(called))
 
         assert len(error_path) == 10
-
-
-    """
-    @slow
-    def test_process_powerwindow_print(self):
-        model_add("formalisms/ReachabilityGraph", "formalisms/SimpleClassDiagrams", open("models/reachability_graph.mvc", "r").read())
-        model_add("formalisms/PetriNet", "formalisms/SimpleClassDiagrams", open("integration/code/pn_design.mvc", 'r').read())
-        model_add("formalisms/Encapsulated_PetriNet", "formalisms/SimpleClassDiagrams", open("models/petrinet_ports.mvc", 'r').read())
-        model_add("formalisms/PW_Plant", "formalisms/SimpleClassDiagrams", open("models/plant_PW.mvc", 'r').read())
-        model_add("formalisms/PW_Environment", "formalisms/SimpleClassDiagrams", open("models/environment_PW.mvc", 'r').read())
-        model_add("formalisms/PW_Control", "formalisms/SimpleClassDiagrams", open("models/control_PW.mvc", 'r').read())
-        model_add("formalisms/Requirements", "formalisms/SimpleClassDiagrams", open("models/requirements.mvc", 'r').read())
-        model_add("formalisms/Query", "formalisms/SimpleClassDiagrams", open("models/query.mvc", 'r').read())
-        model_add("formalisms/Architecture", "formalisms/SimpleClassDiagrams", open("models/architecture.mvc", 'r').read())
-
-        model_add("models/pm_powerwindow", "formalisms/ProcessModel", open("models/pm_req_analyse_print.mvc", 'r').read())
-
-        transformation_add_MANUAL({"Requirements": "formalisms/Requirements"}, {"Requirements": "formalisms/Requirements"}, "models/revise_req")
-        transformation_add_MANUAL({"Requirements": "formalisms/Requirements", "PW_Environment": "formalisms/PW_Environment"}, {"PW_Environment": "formalisms/PW_Environment"}, "models/revise_environment")
-        transformation_add_MANUAL({"Requirements": "formalisms/Requirements", "PW_Plant": "formalisms/PW_Plant"}, {"PW_Plant": "formalisms/PW_Plant"}, "models/revise_plant")
-        transformation_add_MANUAL({"Requirements": "formalisms/Requirements", "PW_Control": "formalisms/PW_Control"}, {"PW_Control": "formalisms/PW_Control"}, "models/revise_control")
-        transformation_add_MANUAL({"Requirements": "formalisms/Requirements", "Query": "formalisms/Query"}, {"Query": "formalisms/Query"}, "models/revise_query")
-        transformation_add_MANUAL({"Requirements": "formalisms/Requirements", "Architecture": "formalisms/Architecture"}, {"Architecture": "formalisms/Architecture"}, "models/revise_architecture")
-
-        def tracability_CTRL2EPN(model):
-            instantiate(model, "Association", ("PW_Control/State", "Encapsulated_PetriNet/Place"), ID="CTRL2EPN_link")
-            instantiate(model, "Association", ("PW_Control/Transition", "Encapsulated_PetriNet/Transition"), ID="CTRL2EPN_tlink")
-
-        def tracability_PLANT2EPN(model):
-            instantiate(model, "Association", ("PW_Plant/State", "Encapsulated_PetriNet/Place"), ID="PLANT2EPN_link")
-            instantiate(model, "Association", ("PW_Plant/Transition", "Encapsulated_PetriNet/Transition"), ID="PLANT2EPN_tlink")
-
-        def tracability_ENV2EPN(model):
-            instantiate(model, "Association", ("PW_Environment/Event", "Encapsulated_PetriNet/Place"), ID="ENV2EPN_link")
-
-        def tracability_EPN2PN(model):
-            instantiate(model, "Association", ("Encapsulated_PetriNet/Place", "PetriNet/Place"), ID="EPN2PN_transition_link")
-            instantiate(model, "Association", ("Encapsulated_PetriNet/Transition", "PetriNet/Transition"), ID="EPN2PN_place_link")
-
-        transformation_add_MT({}, {"PW_Plant": "formalisms/PW_Plant", "PW_Environment": "formalisms/PW_Environment", "PW_Control": "formalisms/PW_Control", "Query": "formalisms/Query", "Architecture": "formalisms/Architecture", "Requirements": "formalisms/Requirements"}, "models/make_initial_models", open("models/initialize.mvc", 'r').read())
-        transformation_add_MT({"PW_Plant": "formalisms/PW_Plant"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/plant_to_EPN", open("models/plant_to_EPN.mvc", 'r').read(), tracability_PLANT2EPN)
-        transformation_add_MT({"PW_Control": "formalisms/PW_Control"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/control_to_EPN", open("models/control_to_EPN.mvc", 'r').read(), tracability_CTRL2EPN)
-        transformation_add_MT({"PW_Environment": "formalisms/PW_Environment"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/environment_to_EPN", open("models/environment_to_EPN.mvc", 'r').read(), tracability_ENV2EPN)
-        transformation_add_MT({"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet", "Architecture": "formalisms/Architecture"}, {"PetriNet": "formalisms/PetriNet"}, "models/combine_EPN", open("models/combine_EPN.mvc", 'r').read(), tracability_EPN2PN)
-        transformation_add_MT({"ReachabilityGraph": "formalisms/ReachabilityGraph", "Query": "formalisms/Query"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/match", open("models/matches.mvc", 'r').read())
-        transformation_add_MT({"ReachabilityGraph": "formalisms/ReachabilityGraph"}, {}, "models/reachability_graph_print", open("models/reachabilitygraph_print.mvc", 'r').read())
-
-        transformation_add_AL({"PetriNet": "formalisms/PetriNet"}, {"ReachabilityGraph": "formalisms/ReachabilityGraph"}, "models/reachability", open("models/reachability.alc", 'r').read())
-        transformation_add_AL({"ReachabilityGraph": "formalisms/ReachabilityGraph"}, {}, "models/bfs", open("models/bfs.alc", 'r').read())
-        transformation_add_AL({"EPN_Plant": "formalisms/Encapsulated_PetriNet", "EPN_Control": "formalisms/Encapsulated_PetriNet", "EPN_Environment": "formalisms/Encapsulated_PetriNet"}, {"Encapsulated_PetriNet": "formalisms/Encapsulated_PetriNet"}, "models/merge_EPN", open("models/merge_EPN.alc", 'r').read())
-
-        nr_of_operations = 6
-
-        try:
-            shutil.rmtree(".TEST_POWER_WINDOW")
-        except:
-            pass
-        os.makedirs(".TEST_POWER_WINDOW")
-
-        def get_function(filename):
-            def func(model):
-                import uuid
-                import os
-                called = len(os.listdir(".TEST_POWER_WINDOW/"))
-                if called > nr_of_operations:
-                    raise Exception("Seemingly called some operation twice!")
-                else:
-                    f = open(".TEST_POWER_WINDOW/%s" % str(uuid.uuid4()), 'w')
-                    f.write(filename)
-                    f.close()
-                model_overwrite(model, open(filename, "r").read())
-            return func
-
-        cb_req = get_function("models/requirements_model.mvc")
-        cb_plant = get_function("models/plant_model.mvc")
-        cb_env = get_function("models/environment_model.mvc")
-        cb_ctrl = get_function("models/control_model.mvc")
-        cb_query = get_function("models/query_model.mvc")
-        cb_arch = get_function("models/architecture_model.mvc")
-
-        callbacks = {
-                "models/revise_req": cb_req,
-                "models/revise_plant": cb_plant,
-                "models/revise_environment": cb_env,
-                "models/revise_control": cb_ctrl,
-                "models/revise_query": cb_query,
-                "models/revise_architecture": cb_arch,
-            }
-
-        try:
-            process_execute("models/pm_powerwindow", {}, callbacks)
-        except:
-            import traceback
-            print(traceback.format_exc())
-
-        called = len(os.listdir(".TEST_POWER_WINDOW/"))
-        shutil.rmtree(".TEST_POWER_WINDOW")
-        if called != 6:
-            print(called)
-            raise Exception("Not executed sufficiently:" + str(called))
-    """

+ 9 - 13
integration/utils.py

@@ -5,16 +5,11 @@ import os
 import sys
 import time
 import json
-
-
-if sys.version_info[0] < 3:
-    from urllib2 import urlopen as urlopen
-    from urllib2 import Request as Request
-    from urllib import urlencode as urlencode
-else:
-    from urllib.request import urlopen as urlopen
-    from urllib.request import Request as Request
-    from urllib.parse import urlencode as urlencode
+import urllib
+try:
+    import urllib2
+except ImportError:
+    import urllib as urllib2
 
 import subprocess
 import signal
@@ -22,7 +17,7 @@ import random
 
 sys.path.append("interface/HUTN")
 sys.path.append("scripts")
-from hutn_compiler.compiler import main as do_compile
+#from interface.HUTN.hutn_compiler.compiler import main as do_compile
 
 taskname = "test_task"
 INIT_TIMEOUT = 30
@@ -64,7 +59,7 @@ def child_kill(pid):
     subprocess.call(["pkill", "-P", "%i" % pid])
     start = time.time()
     with open(os.devnull, 'w') as null:
-        while subprocess.call(["pgrep", "-P", "%i" % pid], stdout=null) != 1:
+        while subprocess.call(["pgrep", "-P", "%i" % pid], stdout=null) > 1:
             time.sleep(0.1)
             if time.time() > start + 4:
                 subprocess.call(["pkill", "-9", "-P", "%i" % pid])
@@ -81,11 +76,12 @@ def kill(process):
 
 def flush_data(address, data):
     if data:
-        urlopen(Request(address, urlencode({"op": "set_input", "data": json.dumps(data), "taskname": taskname})), timeout=INIT_TIMEOUT).read()
+        urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "data": json.dumps(data), "taskname": taskname})), timeout=INIT_TIMEOUT).read()
     return []
 
 def start_mvc():
     port = getFreePort()
     address = "127.0.0.1:%s" % port
+    print("Execute run local MV")
     proc = execute("run_local_modelverse", [str(port)], wait=False)
     return proc, address

+ 0 - 1
interface/HUTN/hutn_compiler/model_visitor.py

@@ -138,7 +138,6 @@ class ModelVisitor(Visitor):
                 attr_value = attr_value.get_text()[1:-1]
             elif attr_value.head == "LONG_STR":
                 attr_value = attr_value.get_text()[3:-3]
-                print("Got value: " + str(attr_value))
             elif attr_value.head == "TRUE":
                 attr_value = True
             elif attr_value.head == "FALSE":

+ 0 - 2
interface/HUTN/includes/jit.alh

@@ -1,2 +0,0 @@
-Boolean function get_jit_enabled()
-Void function set_jit_enabled(a: Boolean)

+ 16 - 1
interface/simple_plot/main.py

@@ -26,6 +26,7 @@ maps = {}
 if time <= old_time:
     # Overwrites current values, so flush
     d = {}
+    plt.legend()
 else:
     for key in d:
         maps[key], = plt.plot(d[key][0], d[key][1])
@@ -48,7 +49,12 @@ while 1:
         continue
     time, key, value = l.split(" ")
     time = float(time)
-    value = float(value)
+    try:
+        value = float(value)
+    except:
+        # Value is not a number, so we work with discrete states, just ignore!
+        pass
+        value = value.strip()
 
     if key not in maps:
         maps[key], = plt.plot([], [])
@@ -60,6 +66,15 @@ while 1:
 
     d[key][0].append(time)
     d[key][1].append(value)
+
+    if isinstance(value, str) and value not in d[key][1][:-1]:
+        for key in d:
+            prev_color = maps[key].get_color()
+            maps[key].remove()
+            maps[key], = plt.plot(d[key][0], d[key][1], c=prev_color)
+            maps[key].set_label(key)
+        plt.legend()
+
     maps[key].set_xdata(d[key][0])
     maps[key].set_ydata(d[key][1])
     plt.gca().set_xlim([min(d[key][0]), max(d[key][0])])

+ 0 - 319
kernel/modelverse_jit/bytecode_interpreter.py

@@ -1,319 +0,0 @@
-"""Interprets parsed bytecode graphs."""
-
-import modelverse_jit.bytecode_ir as bytecode_ir
-import modelverse_jit.runtime as jit_runtime
-import modelverse_kernel.primitives as primitive_functions
-
-class BreakException(Exception):
-    """A type of exception that is used to interpret 'break' instructions:
-       the 'break' instructions throw a BreakException, which is then handled
-       by the appropriate 'while' instruction."""
-    def __init__(self, loop):
-        Exception.__init__(self)
-        self.loop = loop
-
-class ContinueException(Exception):
-    """A type of exception that is used to interpret 'continue' instructions:
-       the 'continue' instructions throw a ContinueException, which is then handled
-       by the appropriate 'while' instruction."""
-    def __init__(self, loop):
-        Exception.__init__(self)
-        self.loop = loop
-
-class InterpreterState(object):
-    """The state of the bytecode interpreter."""
-    def __init__(self, gc_root_node, keyword_arg_dict, nop_period=20):
-        self.gc_root_node = gc_root_node
-        self.nop_period = nop_period
-        self.keyword_arg_dict = keyword_arg_dict
-        self.current_result = None
-        self.nop_phase = 0
-        self.local_vars = {}
-
-    def import_local(self, node_id, value):
-        """Imports the given value as a local in this interpreter state."""
-        local_node, = yield [("CN", [])]
-        yield [
-            ("CE", [self.gc_root_node, local_node]),
-            ("CD", [local_node, "value", value])]
-        self.local_vars[node_id] = local_node
-        raise primitive_functions.PrimitiveFinished(None)
-
-    def schedule_nop(self):
-        """Increments the nop-phase. If a nop should be performed, then True is returned.
-           Otherwise, False."""
-        self.nop_phase += 1
-        if self.nop_phase == self.nop_period:
-            self.nop_phase = 0
-            return True
-        else:
-            return False
-
-    def update_result(self, new_result):
-        """Sets the current result to the given value, if it is not None."""
-        if new_result is not None:
-            self.current_result = new_result
-
-    def get_task_root(self):
-        """Gets the task root node id."""
-        return self.keyword_arg_dict['task_root']
-
-    def get_kernel(self):
-        """Gets the Modelverse kernel instance."""
-        return self.keyword_arg_dict['mvk']
-
-    def interpret(self, instruction):
-        """Interprets the given instruction and returns the current result."""
-        instruction_type = type(instruction)
-        if instruction_type in InterpreterState.INTERPRETERS:
-            # Interpret the instruction.
-            yield [("CALL_ARGS",
-                    [InterpreterState.INTERPRETERS[instruction_type], (self, instruction)])]
-
-            # Maybe perform a nop.
-            if self.schedule_nop():
-                yield None
-
-            # Interpret the next instruction.
-            next_instruction = instruction.next_instruction
-            if next_instruction is not None:
-                yield [("TAIL_CALL_ARGS", [self.interpret, (next_instruction,)])]
-            else:
-                raise primitive_functions.PrimitiveFinished(self.current_result)
-        else:
-            raise jit_runtime.JitCompilationFailedException(
-                'Unknown bytecode instruction: %r' % instruction)
-
-    def interpret_select(self, instruction):
-        """Interprets the given 'select' instruction."""
-        cond_node, = yield [("CALL_ARGS", [self.interpret, (instruction.condition,)])]
-        cond_val, = yield [("RV", [cond_node])]
-        if cond_val:
-            yield [("TAIL_CALL_ARGS", [self.interpret, (instruction.if_clause,)])]
-        elif instruction.else_clause is not None:
-            yield [("TAIL_CALL_ARGS", [self.interpret, (instruction.else_clause,)])]
-        else:
-            raise primitive_functions.PrimitiveFinished(None)
-
-    def interpret_while(self, instruction):
-        """Interprets the given 'while' instruction."""
-        def __handle_break(exception):
-            if exception.loop == instruction:
-                # End the loop.
-                raise primitive_functions.PrimitiveFinished(None)
-            else:
-                # Propagate the exception to the next 'while' loop.
-                raise exception
-
-        def __handle_continue(exception):
-            if exception.loop == instruction:
-                # Restart the loop.
-                yield [("TAIL_CALL_ARGS", [self.interpret, (instruction,)])]
-            else:
-                # Propagate the exception to the next 'while' loop.
-                raise exception
-
-        yield [("TRY", [])]
-        yield [("CATCH", [BreakException, __handle_break])]
-        yield [("CATCH", [ContinueException, __handle_continue])]
-        while 1:
-            cond_node, = yield [("CALL_ARGS", [self.interpret, (instruction.condition,)])]
-            cond_val, = yield [("RV", [cond_node])]
-            if cond_val:
-                yield [("CALL_ARGS", [self.interpret, (instruction.body,)])]
-            else:
-                break
-        yield [("END_TRY", [])]
-
-        raise primitive_functions.PrimitiveFinished(None)
-
-    def interpret_break(self, instruction):
-        """Interprets the given 'break' instruction."""
-        raise BreakException(instruction.loop)
-
-    def interpret_continue(self, instruction):
-        """Interprets the given 'continue' instruction."""
-        raise ContinueException(instruction.loop)
-
-    def interpret_return(self, instruction):
-        """Interprets the given 'return' instruction."""
-        if instruction.value is None:
-            raise primitive_functions.InterpretedFunctionFinished(None)
-        else:
-            return_node, = yield [("CALL_ARGS", [self.interpret, (instruction.value,)])]
-            raise primitive_functions.InterpretedFunctionFinished(return_node)
-
-    def interpret_call(self, instruction):
-        """Interprets the given 'call' instruction."""
-        target, = yield [("CALL_ARGS", [self.interpret, (instruction.target,)])]
-        named_args = {}
-        for name, arg_instruction in instruction.argument_list:
-            arg, = yield [("CALL_ARGS", [self.interpret, (arg_instruction,)])]
-            named_args[name] = arg
-
-        kwargs = {'function_id': target, 'named_arguments': named_args}
-        kwargs.update(self.keyword_arg_dict)
-        result, = yield [("CALL_KWARGS", [jit_runtime.call_function, kwargs])]
-        if result is not None:
-            yield [("CE", [self.gc_root_node, result])]
-            self.update_result(result)
-
-        raise primitive_functions.PrimitiveFinished(None)
-
-    def interpret_constant(self, instruction):
-        """Interprets the given 'constant' instruction."""
-        self.update_result(instruction.constant_id)
-        raise primitive_functions.PrimitiveFinished(None)
-
-    def interpret_input(self, instruction):
-        """Interprets the given 'input' instruction."""
-        result, = yield [("CALL_KWARGS", [jit_runtime.get_input, self.keyword_arg_dict])]
-        self.update_result(result)
-        yield [("CE", [self.gc_root_node, result])]
-        raise primitive_functions.PrimitiveFinished(None)
-
-    def interpret_output(self, instruction):
-        """Interprets the given 'output' instruction."""
-        output_value, = yield [("CALL_ARGS", [self.interpret, (instruction.value,)])]
-        task_root = self.get_task_root()
-        last_output, last_output_link, new_last_output = yield [
-            ("RD", [task_root, "last_output"]),
-            ("RDE", [task_root, "last_output"]),
-            ("CN", [])
-        ]
-        yield [
-            ("CD", [last_output, "value", output_value]),
-            ("CD", [last_output, "next", new_last_output]),
-            ("CD", [task_root, "last_output", new_last_output]),
-            ("DE", [last_output_link])
-        ]
-        yield None
-        raise primitive_functions.PrimitiveFinished(None)
-
-    def interpret_declare(self, instruction):
-        """Interprets a 'declare' (local) instruction."""
-        node_id = instruction.variable.node_id
-        if node_id in self.local_vars:
-            self.update_result(self.local_vars[node_id])
-            raise primitive_functions.PrimitiveFinished(None)
-        else:
-            local_node, = yield [("CN", [])]
-            yield [("CE", [self.gc_root_node, local_node])]
-            self.update_result(local_node)
-            self.local_vars[node_id] = local_node
-            raise primitive_functions.PrimitiveFinished(None)
-
-    def interpret_global(self, instruction):
-        """Interprets a (declare) 'global' instruction."""
-        var_name = instruction.variable.name
-        task_root = self.get_task_root()
-        _globals, = yield [("RD", [task_root, "globals"])]
-        global_var, = yield [("RDE", [_globals, var_name])]
-
-        if global_var is not None:
-            yield [("DE", [global_var])]
-
-        global_var, = yield [("CN", [])]
-        yield [("CD", [_globals, var_name, global_var])]
-
-        self.update_result(global_var)
-        yield [("CE", [self.gc_root_node, global_var])]
-        raise primitive_functions.PrimitiveFinished(None)
-
-    def interpret_resolve(self, instruction):
-        """Interprets a 'resolve' instruction."""
-        node_id = instruction.variable.node_id
-        if node_id in self.local_vars:
-            self.update_result(self.local_vars[node_id])
-            raise primitive_functions.PrimitiveFinished(None)
-        else:
-            task_root = self.get_task_root()
-            var_name = instruction.variable.name
-            _globals, = yield [("RD", [task_root, "globals"])]
-            global_var, = yield [("RD", [_globals, var_name])]
-
-            if global_var is None:
-                raise Exception(jit_runtime.GLOBAL_NOT_FOUND_MESSAGE_FORMAT % var_name)
-
-            mvk = self.get_kernel()
-            if mvk.suggest_function_names and mvk.jit.get_global_body_id(var_name) is None:
-                global_val, = yield [("RD", [global_var, "value"])]
-                if global_val is not None:
-                    func_body, = yield [("RD", [global_val, "body"])]
-                    if func_body is not None:
-                        mvk.jit.register_global(func_body, var_name)
-
-            self.update_result(global_var)
-            yield [("CE", [self.gc_root_node, global_var])]
-            raise primitive_functions.PrimitiveFinished(None)
-
-    def interpret_access(self, instruction):
-        """Interprets an 'access' instruction."""
-        pointer_node, = yield [("CALL_ARGS", [self.interpret, (instruction.pointer,)])]
-        value_node, = yield [("RD", [pointer_node, "value"])]
-        self.update_result(value_node)
-        yield [("CE", [self.gc_root_node, value_node])]
-        raise primitive_functions.PrimitiveFinished(None)
-
-    def interpret_assign(self, instruction):
-        """Interprets an 'assign' instruction."""
-        pointer_node, = yield [("CALL_ARGS", [self.interpret, (instruction.pointer,)])]
-        value_node, = yield [("CALL_ARGS", [self.interpret, (instruction.value,)])]
-        value_link, = yield [("RDE", [pointer_node, "value"])]
-        yield [
-            ("CD", [pointer_node, "value", value_node]),
-            ("DE", [value_link])]
-        raise primitive_functions.PrimitiveFinished(None)
-
-    INTERPRETERS = {
-        bytecode_ir.SelectInstruction: interpret_select,
-        bytecode_ir.WhileInstruction: interpret_while,
-        bytecode_ir.BreakInstruction: interpret_break,
-        bytecode_ir.ContinueInstruction: interpret_continue,
-        bytecode_ir.ReturnInstruction: interpret_return,
-        bytecode_ir.CallInstruction: interpret_call,
-        bytecode_ir.ConstantInstruction: interpret_constant,
-        bytecode_ir.InputInstruction: interpret_input,
-        bytecode_ir.OutputInstruction: interpret_output,
-        bytecode_ir.DeclareInstruction: interpret_declare,
-        bytecode_ir.GlobalInstruction: interpret_global,
-        bytecode_ir.ResolveInstruction: interpret_resolve,
-        bytecode_ir.AccessInstruction: interpret_access,
-        bytecode_ir.AssignInstruction: interpret_assign
-    }
-
-def interpret_bytecode_function(function_name, body_bytecode, local_arguments, keyword_arguments):
-    """Interprets the bytecode function with the given name, body, named arguments and
-       keyword arguments."""
-    yield [("DEBUG_INFO", [function_name, None, jit_runtime.BYTECODE_INTERPRETER_ORIGIN_NAME])]
-    task_root = keyword_arguments['task_root']
-    gc_root_node, = yield [("CN", [])]
-    gc_root_edge, = yield [("CE", [task_root, gc_root_node])]
-    interpreter = InterpreterState(gc_root_node, keyword_arguments)
-    for param_id, arg_node in list(local_arguments.items()):
-        yield [("CALL_ARGS", [interpreter.import_local, (param_id, arg_node)])]
-
-    def __handle_return(exception):
-        yield [("DE", [gc_root_edge])]
-        raise primitive_functions.PrimitiveFinished(exception.result)
-
-    def __handle_break(_):
-        raise jit_runtime.UnreachableCodeException(
-            "Function '%s' tries to break out of a loop that is not currently executing." %
-            function_name)
-
-    def __handle_continue(_):
-        raise jit_runtime.UnreachableCodeException(
-            "Function '%s' tries to continue a loop that is not currently executing." %
-            function_name)
-
-    # Perform a nop before interpreting the function.
-    yield None
-
-    yield [("TRY", [])]
-    yield [("CATCH", [primitive_functions.InterpretedFunctionFinished, __handle_return])]
-    yield [("CATCH", [BreakException, __handle_break])]
-    yield [("CATCH", [ContinueException, __handle_continue])]
-    yield [("CALL_ARGS", [interpreter.interpret, (body_bytecode,)])]
-    yield [("END_TRY", [])]
-    raise jit_runtime.UnreachableCodeException("Function '%s' failed to return." % function_name)

+ 0 - 312
kernel/modelverse_jit/bytecode_ir.py

@@ -1,312 +0,0 @@
-"""Provides data structures that represent parsed Modelverse bytecode graphs."""
-
-class Instruction(object):
-    """Represents a Modelverse bytecode instruction."""
-    def __init__(self):
-        self.next_instruction = None
-        self.debug_information = None
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction, excluding the
-           next instruction."""
-        raise NotImplementedError()
-
-    def get_reachable(self, filter_children=lambda _: True):
-        """Gets the set of all instructions that are reachable from the given instruction, including
-           this instruction. A function can be used to filter out certain instructions' children."""
-        results = set()
-        stack = [self]
-        while len(stack) > 0:
-            instr = stack.pop()
-            results.add(instr)
-            next_instr = instr.next_instruction
-            if next_instr is not None and next_instr not in results:
-                stack.append(next_instr)
-
-            if filter_children(instr):
-                for other in instr.get_directly_reachable():
-                    if other not in results:
-                        assert other is not None
-                        stack.append(other)
-
-        return results
-
-class VariableNode(object):
-    """Represents a variable node, which has an identifier and an optional name."""
-    def __init__(self, node_id, name):
-        self.node_id = node_id
-        if node_id is None:
-            print(locals())
-            raise Exception("NONE")
-        self.name = name
-
-    def __str__(self):
-        return 'var(%d, %s)' % (self.node_id, self.name)
-
-    def __repr__(self):
-        return 'VariableNode(%r, %r)' % (self.node_id, self.name)
-
-class SelectInstruction(Instruction):
-    """Represents an 'if/else' instruction."""
-    def __init__(self, condition, if_clause, else_clause):
-        Instruction.__init__(self)
-        self.condition = condition
-        self.if_clause = if_clause
-        self.else_clause = else_clause
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        if self.else_clause is None:
-            return (self.condition, self.if_clause)
-        else:
-            return (self.condition, self.if_clause, self.else_clause)
-
-    constructor_parameters = (
-        ('cond', Instruction),
-        ('then', Instruction),
-        ('else', Instruction))
-
-    def __repr__(self):
-        return '@%r: SelectInstruction(@%r, @%r, @%r)' % (
-            id(self), id(self.condition), id(self.if_clause), id(self.else_clause))
-
-class WhileInstruction(Instruction):
-    """Represents a 'while' instruction."""
-    def __init__(self, condition, body):
-        Instruction.__init__(self)
-        self.condition = condition
-        self.body = body
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        return (self.condition, self.body)
-
-    constructor_parameters = (
-        ('cond', Instruction),
-        ('body', Instruction))
-
-    def __repr__(self):
-        return '@%r: WhileInstruction(@%r, @%r)' % (
-            id(self), id(self.condition), id(self.body))
-
-class BreakInstruction(Instruction):
-    """Represents a 'break' instruction."""
-    def __init__(self, loop):
-        Instruction.__init__(self)
-        self.loop = loop
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        return (self.loop,)
-
-    constructor_parameters = (('while', WhileInstruction),)
-
-    def __repr__(self):
-        return '@%r: BreakInstruction(@%r)' % (
-            id(self), id(self.loop))
-
-class ContinueInstruction(Instruction):
-    """Represents a 'continue' instruction."""
-    def __init__(self, loop):
-        Instruction.__init__(self)
-        self.loop = loop
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        return (self.loop,)
-
-    constructor_parameters = (('while', WhileInstruction),)
-
-    def __repr__(self):
-        return '@%r: ContinueInstruction(@%r)' % (
-            id(self), id(self.loop))
-
-class ReturnInstruction(Instruction):
-    """Represents a 'return' instruction, which terminates the current function
-       and optionally returns a value."""
-    def __init__(self, value):
-        Instruction.__init__(self)
-        self.value = value
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        if self.value is None:
-            return ()
-        else:
-            return (self.value,)
-
-    constructor_parameters = (('value', Instruction),)
-
-    def __repr__(self):
-        return '@%r: ReturnInstruction(@%r)' % (
-            id(self), id(self.value))
-
-class CallInstruction(Instruction):
-    """Represents a 'call' instruction, which calls a function with an argument
-       list, encoded as a list of name-instruction tuples."""
-    def __init__(self, target, argument_list):
-        Instruction.__init__(self)
-        self.target = target
-        self.argument_list = argument_list
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        return (self.target,) + tuple((value for _, value in self.argument_list))
-
-    def __repr__(self):
-        return '@%r: CallInstruction(@%r, [%s])' % (
-            id(self), id(self.target),
-            ', '.join(['%s=@%r' % (name, id(value)) for name, value in self.argument_list]))
-
-class ConstantInstruction(Instruction):
-    """Represents a 'constant' instruction, which produces a reference
-       to a constant node."""
-    def __init__(self, constant_id):
-        Instruction.__init__(self)
-        self.constant_id = constant_id
-        assert self.constant_id is not None
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        return ()
-
-    constructor_parameters = (('node', int),)
-
-    def __repr__(self):
-        return '@%r: ConstantInstruction(%r)' % (id(self), self.constant_id)
-
-class InputInstruction(Instruction):
-    """Represents an 'input' instruction, which pops a node from the input
-       queue."""
-    def __init__(self):
-        Instruction.__init__(self)
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        return ()
-
-    constructor_parameters = ()
-
-    def __repr__(self):
-        return '@%r: InputInstruction()' % id(self)
-
-class OutputInstruction(Instruction):
-    """Represents an 'output' instruction, which pushes a node onto the output
-       queue."""
-    def __init__(self, value):
-        Instruction.__init__(self)
-        self.value = value
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        return (self.value,)
-
-    constructor_parameters = (('value', Instruction),)
-
-    def __repr__(self):
-        return '@%r: OutputInstruction(@%r)' % (
-            id(self), id(self.value))
-
-class DeclareInstruction(Instruction):
-    """Represents a 'declare' instruction, which declares a local variable."""
-    def __init__(self, variable):
-        Instruction.__init__(self)
-        self.variable = variable
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        return ()
-
-    constructor_parameters = (('var', VariableNode),)
-
-    def __repr__(self):
-        return '@%r: DeclareInstruction(%r)' % (
-            id(self), self.variable)
-
-class GlobalInstruction(Instruction):
-    """Represents a 'global' instruction, which declares a global variable."""
-    def __init__(self, variable):
-        Instruction.__init__(self)
-        self.variable = variable
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        return ()
-
-    constructor_parameters = (('var', VariableNode),)
-
-    def __repr__(self):
-        return '@%r: GlobalInstruction(%r)' % (
-            id(self), self.variable)
-
-class ResolveInstruction(Instruction):
-    """Represents a 'resolve' instruction, which resolves a variable node/name as
-       either a local or global variable."""
-    def __init__(self, variable):
-        Instruction.__init__(self)
-        self.variable = variable
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        return ()
-
-    constructor_parameters = (('var', VariableNode),)
-
-    def __repr__(self):
-        return '@%r: ResolveInstruction(%r)' % (
-            id(self), self.variable)
-
-class AccessInstruction(Instruction):
-    """Represents an 'access' instruction, which loads the node pointed to by a
-       pointer node."""
-    def __init__(self, pointer):
-        Instruction.__init__(self)
-        self.pointer = pointer
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        return (self.pointer,)
-
-    constructor_parameters = (('var', Instruction),)
-
-    def __repr__(self):
-        return '@%r: AccessInstruction(@%r)' % (
-            id(self), id(self.pointer))
-
-class AssignInstruction(Instruction):
-    """Represents an 'assign' instruction, which sets the node pointed to by a
-       pointer node to the given node."""
-    def __init__(self, pointer, value):
-        Instruction.__init__(self)
-        self.pointer = pointer
-        self.value = value
-
-    def get_directly_reachable(self):
-        """Gets all instructions that are directly reachable from this instruction."""
-        return (self.pointer, self.value)
-
-    constructor_parameters = (
-        ('var', Instruction),
-        ('value', Instruction))
-
-    def __repr__(self):
-        return '@%r: AssignInstruction(@%r, @%r)' % (
-            id(self), id(self.pointer), id(self.value))
-
-INSTRUCTION_TYPE_MAPPING = {
-    'if' : SelectInstruction,
-    'while' : WhileInstruction,
-    'return' : ReturnInstruction,
-    'constant' : ConstantInstruction,
-    'resolve' : ResolveInstruction,
-    'declare' : DeclareInstruction,
-    'global' : GlobalInstruction,
-    'assign' : AssignInstruction,
-    'access' : AccessInstruction,
-    'output' : OutputInstruction,
-    'input' : InputInstruction,
-    'call' : CallInstruction,
-    'break' : BreakInstruction,
-    'continue' : ContinueInstruction
-}
-"""Maps instruction names to types."""

+ 0 - 117
kernel/modelverse_jit/bytecode_parser.py

@@ -1,117 +0,0 @@
-"""Parses Modelverse bytecode graphs into bytecode ir."""
-
-import modelverse_jit.bytecode_ir as bytecode_ir
-import modelverse_jit.runtime as jit_runtime
-import modelverse_kernel.primitives as primitive_functions
-
-class BytecodeParser(object):
-    """Parses bytecode graphs."""
-    def __init__(self):
-        self.parsed_nodes = {}
-
-    def parse_instruction(self, node_id):
-        """Parses the instruction node with the given identifier."""
-        if node_id is None:
-            raise primitive_functions.PrimitiveFinished(None)
-        elif node_id in self.parsed_nodes:
-            # We've already parsed this node, so return it right away.
-            raise primitive_functions.PrimitiveFinished(self.parsed_nodes[node_id])
-
-        instruction_val, = yield [("RV", [node_id])]
-        instruction_type = instruction_val["value"]
-        # Create an instruction and store it in the instruction dictionary.
-        instruction = self.create_instruction(instruction_type)
-        self.parsed_nodes[node_id] = instruction
-        # Initialize the instruction from the node's data.
-        yield [("CALL_ARGS", [self.initialize_instruction, (instruction, node_id)])]
-        # Retrieve the debug information.
-        debug_info, = yield [("RD", [node_id, "__debug"])]
-        if debug_info is not None:
-            debug_info, = yield [("RV", [debug_info])]
-            instruction.debug_information = debug_info
-
-        # Check if the instruction has a 'next' instruction.
-        next_instr_id, = yield [("RD", [node_id, "next"])]
-        if next_instr_id is not None:
-            instruction.next_instruction, = yield [
-                ("CALL_ARGS", [self.parse_instruction, (next_instr_id,)])]
-
-        raise primitive_functions.PrimitiveFinished(instruction)
-
-    def parse_variable(self, node_id):
-        """Parses the given variable node."""
-        var_name, = yield [("RV", [node_id])]
-        raise primitive_functions.PrimitiveFinished(
-            bytecode_ir.VariableNode(node_id, var_name))
-
-    def __parse_node_unchecked(self, node_id, result_type):
-        """Parses the given node as the specified type of object, without
-           checking that the result actually conforms to said type."""
-        if result_type is bytecode_ir.VariableNode:
-            yield [("TAIL_CALL_ARGS", [self.parse_variable, (node_id,)])]
-        elif result_type is int:
-            raise primitive_functions.PrimitiveFinished(node_id)
-        else:
-            yield [("TAIL_CALL_ARGS", [self.parse_instruction, (node_id,)])]
-
-    def parse_node(self, node_id, result_type):
-        """Parses the given node as the specified type of object."""
-        result, = yield [("CALL_ARGS", [self.__parse_node_unchecked, (node_id, result_type)])]
-        if result is not None and not isinstance(result, result_type):
-            raise jit_runtime.JitCompilationFailedException(
-                "Parsed a node as an instance of '%s', expected an instance of '%s'." % (
-                    type(result).__name__, result_type.__name__))
-
-        raise primitive_functions.PrimitiveFinished(result)
-
-    def parse_arguments(self, first_argument_id):
-        """Parses the parameter-to-argument mapping started by the specified first argument
-           node."""
-        next_param = first_argument_id
-        named_args = []
-        while next_param is not None:
-            param_name_id, = yield [("RD", [next_param, "name"])]
-            param_name, = yield [("RV", [param_name_id])]
-            param_val_id, = yield [("RD", [next_param, "value"])]
-            param_val, = yield [("CALL_ARGS", [self.parse_instruction, (param_val_id,)])]
-            named_args.append((param_name, param_val))
-
-            next_param, = yield [("RD", [next_param, "next_param"])]
-
-        raise primitive_functions.PrimitiveFinished(named_args)
-
-    def create_instruction(self, instruction_type):
-        """Creates an instruction of the given type."""
-        if instruction_type in bytecode_ir.INSTRUCTION_TYPE_MAPPING:
-            return object.__new__(bytecode_ir.INSTRUCTION_TYPE_MAPPING[instruction_type])
-        else:
-            raise jit_runtime.JitCompilationFailedException(
-                "Unknown instruction type: '%s'" % instruction_type)
-
-    def initialize_call(self, call_instruction, node_id):
-        """Initializes the given call instruction."""
-        func_id, first_arg_id, = yield [
-            ("RD", [node_id, "func"]),
-            ("RD", [node_id, "params"])]
-        func_val, = yield [("CALL_ARGS", [self.parse_instruction, (func_id,)])]
-        named_args, = yield [("CALL_ARGS", [self.parse_arguments, (first_arg_id,)])]
-        call_instruction.__init__(func_val, named_args)
-        raise primitive_functions.PrimitiveFinished(None)
-
-    def initialize_instruction(self, instruction, node_id):
-        """Initializes the given instruction with data from the given node."""
-        instr_type = type(instruction)
-        # print("Initializing '%s' node" % instr_type)
-        if instr_type is bytecode_ir.CallInstruction:
-            # Call instructions are complicated, so they get special treatment.
-            yield [("TAIL_CALL_ARGS", [self.initialize_call, (instruction, node_id)])]
-        else:
-            # Construct an argument list based on the `constructor_parameters` attribute
-            # of the instruction type.
-            arg_list = []
-            for dict_key, ctor_param_ty in instr_type.constructor_parameters:
-                arg_id, = yield [("RD", [node_id, dict_key])]
-                arg, = yield [("CALL_ARGS", [self.parse_node, (arg_id, ctor_param_ty)])]
-                arg_list.append(arg)
-            instruction.__init__(*arg_list)
-            raise primitive_functions.PrimitiveFinished(None)

+ 0 - 374
kernel/modelverse_jit/bytecode_to_cfg.py

@@ -1,374 +0,0 @@
-"""Converts bytecode IR to CFG IR."""
-
-import modelverse_jit.bytecode_ir as bytecode_ir
-import modelverse_jit.cfg_ir as cfg_ir
-import modelverse_jit.runtime as jit_runtime
-
-def emit_debug_info_trace(block, debug_info, function_name):
-    """Appends a tracing instruction to the given block that prints
-       the given debug information and function name."""
-    if debug_info is not None or function_name is not None:
-        block.append_definition(
-            cfg_ir.create_print(
-                block.append_definition(
-                    cfg_ir.Literal(jit_runtime.format_trace_message(
-                        debug_info, function_name, jit_runtime.FAST_JIT_ORIGIN_NAME)))))
-
-class AnalysisState(object):
-    """State that is common to the bytecode->CFG transformation of a function."""
-    def __init__(self, jit, function_name, param_dict):
-        self.jit = jit
-        self.function_name = function_name
-        self.counter = cfg_ir.SharedCounter()
-        self.analyzed_instructions = set()
-        self.loop_instructions = {}
-        self.entry_point = cfg_ir.BasicBlock(self.counter)
-        self.current_block = self.entry_point
-        self.root_node = None
-        self.__write_prolog(param_dict)
-
-    def __write_prolog(self, param_dict):
-        # Write a prolog in CFG IR.
-        # We want to create the following definition:
-        #
-        #     !entry_point():
-        #         static if self.jit.source_maps_enabled:
-        #             $function_name = literal <function map>
-        #             $source_map_name = literal <source map name>
-        #             $origin_name = literal jit_runtime.FAST_JIT_ORIGIN_NAME
-        #             $_ = direct-call ('macro-positional', void) register_debug_info(
-        #                 function_name=$functionsource_map=$source_map_name)
-        #
-        #         $jit_locals = alloc-root-node
-        #         $_ = declare-local var(...)
-        #         $param_1 = resolve-local var(...)
-        #         $arg_1 = function-parameter ...
-        #         $_ = store $param_1, $arg_1
-        #         ...
-        #
-        #         static if self.jit.nop_insertion_enabled:
-        #             $_ = direct-call ('macro-io', void) nop()
-        #
-        # We also want to store '$jit_locals' in an attribute, so we can
-        # use it to shield locals from the GC.
-        if self.jit.source_maps_enabled:
-            function_name = self.current_block.append_definition(
-                cfg_ir.Literal(self.function_name))
-            source_map_name = self.current_block.append_definition(
-                cfg_ir.Literal(self.jit.get_source_map_name(self.function_name)))
-            origin_name = self.current_block.append_definition(
-                cfg_ir.Literal(jit_runtime.FAST_JIT_ORIGIN_NAME))
-            self.current_block.append_definition(
-                cfg_ir.DirectFunctionCall(
-                    cfg_ir.REGISTER_DEBUG_INFO_MACRO_NAME,
-                    [('function_name', function_name),
-                     ('source_map', source_map_name),
-                     ('origin_name', origin_name)],
-                    calling_convention=cfg_ir.MACRO_POSITIONAL_CALLING_CONVENTION,
-                    has_value=False))
-
-        self.root_node = self.current_block.append_definition(cfg_ir.AllocateRootNode())
-        for node_id, name in list(param_dict.items()):
-            variable = bytecode_ir.VariableNode(node_id, name)
-            self.current_block.append_definition(cfg_ir.DeclareLocal(variable, self.root_node))
-            param_i = self.current_block.append_definition(cfg_ir.ResolveLocal(variable))
-            arg_i = self.current_block.append_definition(cfg_ir.FunctionParameter(name))
-            self.current_block.append_definition(cfg_ir.StoreAtPointer(param_i, arg_i))
-
-        if self.jit.nop_insertion_enabled:
-            self.current_block.append_definition(cfg_ir.create_nop())
-
-    def analyze(self, instruction):
-        """Analyzes the given instruction as a basic block."""
-        if instruction in self.analyzed_instructions:
-            raise jit_runtime.JitCompilationFailedException(
-                'Cannot jit non-tree instruction graph.')
-
-        self.analyzed_instructions.add(instruction)
-
-        # Find an analyzer.
-        instruction_type = type(instruction)
-        if instruction_type in self.instruction_analyzers:
-            if self.jit.tracing_enabled:
-                emit_debug_info_trace(
-                    self.current_block, instruction.debug_information, self.function_name)
-
-            # Analyze the instruction.
-            result = self.instruction_analyzers[instruction_type](self, instruction)
-
-            if self.jit.source_maps_enabled:
-                result.debug_information = instruction.debug_information
-
-            # Check if the instruction has a 'next' instruction. If so, analyze it!
-            if instruction.next_instruction is not None:
-                next_result = self.analyze(instruction.next_instruction)
-                if next_result.value.has_value() or (not result.value.has_value()):
-                    result = next_result
-
-            return result
-        else:
-            raise jit_runtime.JitCompilationFailedException(
-                "Unknown instruction type: '%s'" % type(instruction))
-
-    def emit_select(self, create_condition, create_if_body, create_else_body):
-        """Emits a 'select' instruction."""
-        # Create blocks that look like this:
-        #
-        # !current_block(...):
-        #     ...
-        #     $cond = <condition>
-        #     select $cond, !if_block(), !else_block()
-        #
-        # !if_block():
-        #     $if_result = <if-body>
-        #     jump !phi_block($if_result)
-        #
-        # !else_block():
-        #     $else_result = <else-body>
-        #     jump !phi_block($else_result)
-        #
-        # !phi_block($result = block-parameter):
-        #     ...
-        #
-        if_block = cfg_ir.BasicBlock(self.counter)
-        else_block = cfg_ir.BasicBlock(self.counter)
-        phi_block = cfg_ir.BasicBlock(self.counter)
-        param_def = phi_block.append_parameter(cfg_ir.BlockParameter())
-
-        condition = create_condition()
-        self.current_block.flow = cfg_ir.SelectFlow(
-            condition, cfg_ir.Branch(if_block), cfg_ir.Branch(else_block))
-
-        self.current_block = if_block
-        if_result = create_if_body()
-        self.current_block.flow = cfg_ir.create_jump(phi_block, [if_result])
-
-        self.current_block = else_block
-        else_result = create_else_body()
-        self.current_block.flow = cfg_ir.create_jump(phi_block, [else_result])
-
-        self.current_block = phi_block
-        return param_def
-
-    def analyze_if(self, instruction):
-        """Analyzes an 'if' instruction."""
-        def __analyze_condition():
-            condition_node = self.analyze(instruction.condition)
-            return self.current_block.append_definition(cfg_ir.Read(condition_node))
-        return self.emit_select(
-            __analyze_condition,
-            lambda: self.analyze(instruction.if_clause),
-            lambda:
-            self.current_block.append_definition(cfg_ir.Literal(None))
-            if instruction.else_clause is None
-            else self.analyze(instruction.else_clause))
-
-    def analyze_while(self, instruction):
-        """Analyzes a 'while' instruction."""
-        # Create blocks that look like this:
-        #
-        # !current_block(...):
-        #     ...
-        #     jump !loop_condition()
-        #
-        # !loop_condition():
-        #     $condition_node = <condition>
-        #     $condition = read condition_node
-        #     select $condition, !loop_body(), !loop_exit()
-        #
-        # !loop_body():
-        #     $result = <body>
-        #     static if jit.nop_insertion_enabled:
-        #         $_ = direct-call ('macro-io', void) nop()
-        #     jump !loop_condition()
-        #
-        # !loop_exit():
-        #     $nothing = literal None
-        #     ...
-        loop_condition_block = cfg_ir.BasicBlock(self.counter)
-        loop_body_block = cfg_ir.BasicBlock(self.counter)
-        loop_exit_block = cfg_ir.BasicBlock(self.counter)
-        self.loop_instructions[instruction] = (loop_condition_block, loop_exit_block)
-
-        self.current_block.flow = cfg_ir.create_jump(loop_condition_block)
-
-        self.current_block = loop_condition_block
-        condition_node = self.analyze(instruction.condition)
-        condition = self.current_block.append_definition(cfg_ir.Read(condition_node))
-        self.current_block.flow = cfg_ir.SelectFlow(
-            condition, cfg_ir.Branch(loop_body_block), cfg_ir.Branch(loop_exit_block))
-
-        self.current_block = loop_body_block
-        self.analyze(instruction.body)
-        if self.jit.nop_insertion_enabled:
-            self.current_block.append_definition(cfg_ir.create_nop())
-        self.current_block.flow = cfg_ir.create_jump(loop_condition_block)
-
-        self.current_block = loop_exit_block
-        return loop_exit_block.append_definition(cfg_ir.Literal(None))
-
-    def analyze_return(self, instruction):
-        """Analyzes a 'return' instruction."""
-        if instruction.value is None:
-            return_value = self.current_block.append_definition(cfg_ir.Literal(None))
-        else:
-            return_value = self.analyze(instruction.value)
-        # Don't forget to deallocate the root node.
-        self.current_block.append_definition(cfg_ir.DeallocateRootNode(self.root_node))
-        self.current_block.flow = cfg_ir.ReturnFlow(return_value)
-        self.current_block = cfg_ir.BasicBlock(self.counter)
-        return self.current_block.append_definition(cfg_ir.Literal(None))
-
-    def analyze_constant(self, instruction):
-        """Analyzes a 'constant' instruction."""
-        return self.current_block.append_definition(cfg_ir.Literal(instruction.constant_id))
-
-    def analyze_resolve(self, instruction):
-        """Analyzes a 'resolve' instruction."""
-        def __resolve_global_carefully():
-            # We might be resolving a global that does not exist. In that case, we
-            # need to throw. We want to create the following blocks:
-            #
-            # !current_block(...):
-            #     ...
-            #     $resolved_global = resolve-global global
-            #     $nothing = literal None
-            #     $condition = binary $resolved_global, 'is', $nothing
-            #     select $condition, !no_global_block(), !global_exists_block()
-            #
-            # !no_global_block():
-            #     $message = literal <GLOBAL_NOT_FOUND_MESSAGE_FORMAT % instruction.variable.name>
-            #     $exception = direct-call "simple-positional" Exception(message=$message)
-            #     throw $exception
-            #
-            # !global_exists_block():
-            #     ...
-            #
-            no_global_block = cfg_ir.BasicBlock(self.counter)
-            global_exists_block = cfg_ir.BasicBlock(self.counter)
-
-            resolved_global = self.current_block.append_definition(
-                cfg_ir.ResolveGlobal(instruction.variable))
-            nothing = self.current_block.append_definition(cfg_ir.Literal(None))
-            condition = self.current_block.append_definition(
-                cfg_ir.Binary(resolved_global, 'is', nothing))
-            self.current_block.flow = cfg_ir.SelectFlow(
-                condition, cfg_ir.Branch(no_global_block), cfg_ir.Branch(global_exists_block))
-
-            message = no_global_block.append_definition(
-                cfg_ir.Literal(
-                    jit_runtime.GLOBAL_NOT_FOUND_MESSAGE_FORMAT % instruction.variable.name))
-            exception = no_global_block.append_definition(
-                cfg_ir.DirectFunctionCall(
-                    'Exception',
-                    [('message', message)],
-                    cfg_ir.SIMPLE_POSITIONAL_CALLING_CONVENTION))
-            no_global_block.flow = cfg_ir.ThrowFlow(exception)
-
-            self.current_block = global_exists_block
-            return resolved_global
-        return self.emit_select(
-            lambda:
-            self.current_block.append_definition(
-                cfg_ir.CheckLocalExists(instruction.variable)),
-            lambda:
-            self.current_block.append_definition(
-                cfg_ir.ResolveLocal(instruction.variable)),
-            __resolve_global_carefully)
-
-    def analyze_declare(self, instruction):
-        """Analyzes a 'declare' instruction."""
-        return self.current_block.append_definition(
-            cfg_ir.DeclareLocal(instruction.variable, self.root_node))
-
-    def analyze_global(self, instruction):
-        """Analyzes a 'global' instruction."""
-
-        return self.current_block.append_definition(
-            cfg_ir.DeclareGlobal(instruction.variable))
-
-        """
-        resolved_global = self.current_block.append_definition(
-            cfg_ir.ResolveGlobal(instruction.variable))
-        nothing = self.current_block.append_definition(cfg_ir.Literal(None))
-        return self.emit_select(
-            lambda:
-            self.current_block.append_definition(
-                cfg_ir.Binary(resolved_global, 'is', nothing)),
-            lambda:
-            self.current_block.append_definition(
-                cfg_ir.DeclareGlobal(instruction.variable)),
-            lambda: resolved_global)
-        """
-
-    def analyze_assign(self, instruction):
-        """Analyzes an 'assign' instruction."""
-        pointer_result = self.analyze(instruction.pointer)
-        value_result = self.analyze(instruction.value)
-        return self.current_block.append_definition(
-            cfg_ir.StoreAtPointer(pointer_result, value_result))
-
-    def analyze_access(self, instruction):
-        """Analyzes an 'access' instruction."""
-        pointer_result = self.analyze(instruction.pointer)
-        return self.current_block.append_definition(cfg_ir.LoadPointer(pointer_result))
-
-    def analyze_output(self, instruction):
-        """Analyzes an 'output' instruction."""
-        value_result = self.analyze(instruction.value)
-        return self.current_block.append_definition(cfg_ir.create_output(value_result))
-
-    def analyze_input(self, _):
-        """Analyzes an 'input' instruction."""
-        return self.current_block.append_definition(cfg_ir.create_input())
-
-    def analyze_break(self, instruction):
-        """Analyzes a 'break' instruction."""
-        if instruction.loop not in self.loop_instructions:
-            raise jit_runtime.JitCompilationFailedException(
-                "'break' instruction targets a 'while' loop that has not been defined yet.")
-
-        _, exit_block = self.loop_instructions[instruction.loop]
-        self.current_block.flow = cfg_ir.create_jump(exit_block)
-        self.current_block = cfg_ir.BasicBlock(self.counter)
-        return self.current_block.append_definition(cfg_ir.Literal(None))
-
-    def analyze_continue(self, instruction):
-        """Analyzes a 'continue' instruction."""
-        if instruction.loop not in self.loop_instructions:
-            raise jit_runtime.JitCompilationFailedException(
-                "'continue' instruction targets a 'while' loop that has not been defined yet.")
-
-        if self.jit.nop_insertion_enabled:
-            self.current_block.append_definition(cfg_ir.create_nop())
-        cond_block, _ = self.loop_instructions[instruction.loop]
-        self.current_block.flow = cfg_ir.create_jump(cond_block)
-        self.current_block = cfg_ir.BasicBlock(self.counter)
-        return self.current_block.append_definition(cfg_ir.Literal(None))
-
-    def analyze_call(self, instruction):
-        """Analyzes the given 'call' instruction."""
-        target = self.analyze(instruction.target)
-        arg_list = []
-        for key, arg_instruction in instruction.argument_list:
-            arg_list.append((key, self.analyze(arg_instruction)))
-
-        return self.current_block.append_definition(cfg_ir.IndirectFunctionCall(target, arg_list))
-
-    instruction_analyzers = {
-        bytecode_ir.SelectInstruction : analyze_if,
-        bytecode_ir.WhileInstruction : analyze_while,
-        bytecode_ir.ReturnInstruction : analyze_return,
-        bytecode_ir.ConstantInstruction : analyze_constant,
-        bytecode_ir.ResolveInstruction : analyze_resolve,
-        bytecode_ir.DeclareInstruction : analyze_declare,
-        bytecode_ir.GlobalInstruction : analyze_global,
-        bytecode_ir.AssignInstruction : analyze_assign,
-        bytecode_ir.AccessInstruction : analyze_access,
-        bytecode_ir.OutputInstruction : analyze_output,
-        bytecode_ir.InputInstruction : analyze_input,
-        bytecode_ir.CallInstruction : analyze_call,
-        bytecode_ir.BreakInstruction : analyze_break,
-        bytecode_ir.ContinueInstruction : analyze_continue
-    }
-

+ 0 - 725
kernel/modelverse_jit/bytecode_to_tree.py

@@ -1,725 +0,0 @@
-"""Naively converts bytecode IR to tree IR."""
-
-import modelverse_jit.bytecode_ir as bytecode_ir
-import modelverse_jit.tree_ir as tree_ir
-import modelverse_jit.runtime as jit_runtime
-import modelverse_kernel.primitives as primitive_functions
-
-def get_parameter_names(compiled_function):
-    """Gets the given compiled function's parameter names."""
-    if hasattr(compiled_function, '__code__'):
-        return compiled_function.__code__.co_varnames[
-            :compiled_function.__code__.co_argcount]
-    elif hasattr(compiled_function, '__init__'):
-        return get_parameter_names(compiled_function.__init__)[1:]
-    else:
-        raise ValueError("'compiled_function' must be a function or a type.")
-
-def apply_intrinsic(intrinsic_function, named_args):
-    """Applies the given intrinsic to the given sequence of named arguments."""
-    param_names = get_parameter_names(intrinsic_function)
-    if tuple(param_names) == tuple([n for n, _ in named_args]):
-        # Perfect match. Yay!
-        return intrinsic_function(**dict(named_args))
-    else:
-        # We'll have to store the arguments into locals to preserve
-        # the order of evaluation.
-        stored_args = [(name, tree_ir.StoreLocalInstruction(None, arg)) for name, arg in named_args]
-        arg_value_dict = dict([(name, arg.create_load()) for name, arg in stored_args])
-        store_instructions = [instruction for _, instruction in stored_args]
-        return tree_ir.CompoundInstruction(
-            tree_ir.create_block(*store_instructions),
-            intrinsic_function(**arg_value_dict))
-
-def retrieve_task_root():
-    """Creates an instruction that stores the task_root variable in a local."""
-    return tree_ir.StoreLocalInstruction(
-        'task_root', load_task_root())
-
-def load_task_root():
-    """Creates an instruction that loads the task_root variable."""
-    return tree_ir.LoadIndexInstruction(
-        tree_ir.LoadLocalInstruction(jit_runtime.KWARGS_PARAMETER_NAME),
-        tree_ir.LiteralInstruction('task_root'))
-
-def load_kernel():
-    """Creates an instruction that loads the Modelverse kernel."""
-    return tree_ir.LoadIndexInstruction(
-        tree_ir.LoadLocalInstruction(jit_runtime.KWARGS_PARAMETER_NAME),
-        tree_ir.LiteralInstruction('mvk'))
-
-def create_access(pointer):
-    """Creates a tree that loads the given pointer's value."""
-    # Accessing a variable is pretty easy. It really just boils
-    # down to reading the value corresponding to the 'value' key
-    # of the variable.
-    #
-    #     value, = yield [("RD", [returnvalue, "value"])]
-    #
-    return tree_ir.ReadDictionaryValueInstruction(
-        pointer,
-        tree_ir.LiteralInstruction('value'))
-
-def create_assign(pointer, value):
-    """Creates a tree that assigns the given value to the given pointer."""
-    # Assignments work like this:
-    #
-    #     value_link = yield [("RDE", [variable, "value"])]
-    #     _, _ =       yield [("CD", [variable, "value", value]),
-    #                         ("DE", [value_link])]
-    #
-    variable = tree_ir.StoreLocalInstruction(None, pointer)
-    value = tree_ir.StoreLocalInstruction(None, value)
-    value_link = tree_ir.StoreLocalInstruction(
-        'value_link',
-        tree_ir.ReadDictionaryEdgeInstruction(
-            variable.create_load(),
-            tree_ir.LiteralInstruction('value')))
-
-    return tree_ir.create_block(
-        variable,
-        value,
-        value_link,
-        tree_ir.CreateDictionaryEdgeInstruction(
-            variable.create_load(),
-            tree_ir.LiteralInstruction('value'),
-            value.create_load()),
-        tree_ir.DeleteEdgeInstruction(
-            value_link.create_load()))
-
-def create_input(use_input_function=False):
-    """Creates an instruction that pops a value from the input queue."""
-    # Possible alternative to the explicit syntax tree: just call the jit_runtime.__get_input
-    # function.
-    use_input_function = True
-    if use_input_function:
-        return tree_ir.create_jit_call(
-            tree_ir.LoadGlobalInstruction(jit_runtime.GET_INPUT_FUNCTION_NAME),
-            [],
-            tree_ir.LoadLocalInstruction(jit_runtime.KWARGS_PARAMETER_NAME))
-
-    # The plan is to generate this tree:
-    #
-    #     value = None
-    #     while True:
-    #         _input = yield [("RD", [task_root, "input"])]
-    #         value = yield [("RD", [_input, "value"])]
-    #
-    #         if value is None:
-    #             kwargs['mvk'].success = False # to avoid blocking
-    #             yield None # nop/interrupt
-    #         else:
-    #             break
-    #
-    #     _next = yield [("RD", [_input, "next"])]
-    #     yield [("CD", [task_root, "input", _next])]
-    #     yield [("CE", [jit_locals, value])]
-    #     yield [("DN", [_input])]
-
-    task_root = retrieve_task_root()
-    _input = tree_ir.StoreLocalInstruction(
-        None,
-        tree_ir.ReadDictionaryValueInstruction(
-            task_root.create_load(),
-            tree_ir.LiteralInstruction('input')))
-
-    value = tree_ir.StoreLocalInstruction(
-        None,
-        tree_ir.ReadDictionaryValueInstruction(
-            _input.create_load(),
-            tree_ir.LiteralInstruction('value')))
-
-    raise primitive_functions.PrimitiveFinished(
-        tree_ir.CompoundInstruction(
-            tree_ir.create_block(
-                task_root,
-                value.create_store(tree_ir.LiteralInstruction(None)),
-                tree_ir.LoopInstruction(
-                    tree_ir.create_block(
-                        _input,
-                        value,
-                        tree_ir.SelectInstruction(
-                            tree_ir.BinaryInstruction(
-                                value.create_load(),
-                                'is',
-                                tree_ir.LiteralInstruction(None)),
-                            tree_ir.create_block(
-                                tree_ir.StoreMemberInstruction(
-                                    load_kernel(),
-                                    'success',
-                                    tree_ir.LiteralInstruction(False)),
-                                tree_ir.NopInstruction()),
-                            tree_ir.BreakInstruction()))),
-                tree_ir.CreateDictionaryEdgeInstruction(
-                    task_root.create_load(),
-                    tree_ir.LiteralInstruction('input'),
-                    tree_ir.ReadDictionaryValueInstruction(
-                        _input.create_load(),
-                        tree_ir.LiteralInstruction('next'))),
-                tree_ir.CreateEdgeInstruction(
-                    tree_ir.LoadLocalInstruction(jit_runtime.LOCALS_NODE_NAME),
-                    value.create_load()),
-                tree_ir.DeleteNodeInstruction(_input.create_load())),
-            value.create_load()))
-
-def create_output(output_value):
-    """Creates an output instruction that outputs the given value."""
-    # The plan is to basically generate this tree:
-    #
-    # value = <some tree>
-    # last_output, last_output_link, new_last_output = \
-    #                 yield [("RD", [task_root, "last_output"]),
-    #                        ("RDE", [task_root, "last_output"]),
-    #                        ("CN", []),
-    #                       ]
-    # _, _, _, _ = \
-    #                 yield [("CD", [last_output, "value", value]),
-    #                        ("CD", [last_output, "next", new_last_output]),
-    #                        ("CD", [task_root, "last_output", new_last_output]),
-    #                        ("DE", [last_output_link])
-    #                       ]
-    # yield None
-
-    value_local = tree_ir.StoreLocalInstruction('value', output_value)
-
-    store_task_root = retrieve_task_root()
-    last_output = tree_ir.StoreLocalInstruction(
-        'last_output',
-        tree_ir.ReadDictionaryValueInstruction(
-            store_task_root.create_load(),
-            tree_ir.LiteralInstruction('last_output')))
-
-    last_output_link = tree_ir.StoreLocalInstruction(
-        'last_output_link',
-        tree_ir.ReadDictionaryEdgeInstruction(
-            store_task_root.create_load(),
-            tree_ir.LiteralInstruction('last_output')))
-
-    new_last_output = tree_ir.StoreLocalInstruction(
-        'new_last_output',
-        tree_ir.CreateNodeInstruction())
-
-    return tree_ir.create_block(
-        value_local,
-        store_task_root,
-        last_output,
-        last_output_link,
-        new_last_output,
-        tree_ir.CreateDictionaryEdgeInstruction(
-            last_output.create_load(),
-            tree_ir.LiteralInstruction('value'),
-            value_local.create_load()),
-        tree_ir.CreateDictionaryEdgeInstruction(
-            last_output.create_load(),
-            tree_ir.LiteralInstruction('next'),
-            new_last_output.create_load()),
-        tree_ir.CreateDictionaryEdgeInstruction(
-            store_task_root.create_load(),
-            tree_ir.LiteralInstruction('last_output'),
-            new_last_output.create_load()),
-        tree_ir.DeleteEdgeInstruction(last_output_link.create_load()),
-        tree_ir.NopInstruction())
-
-def create_indirect_call(target, argument_list):
-    """Creates an indirect call to the function defined by the node with the id computed
-       by the first argument."""
-    # Call the __call_function function to run the interpreter, like so:
-    #
-    # __call_function(function_id, { first_param_name : first_param_val, ... }, **kwargs)
-    #
-    dict_literal = tree_ir.DictionaryLiteralInstruction(
-        [(tree_ir.LiteralInstruction(key), val) for key, val in argument_list])
-    return tree_ir.create_jit_call(
-        tree_ir.LoadGlobalInstruction(jit_runtime.CALL_FUNCTION_NAME),
-        [('function_id', target), ('named_arguments', dict_literal)],
-        tree_ir.LoadLocalInstruction(jit_runtime.KWARGS_PARAMETER_NAME))
-
-def create_return(return_value):
-    """Creates a return statement that returns the given return value."""
-    return tree_ir.ReturnInstruction(
-        tree_ir.CompoundInstruction(
-            return_value,
-            tree_ir.DeleteEdgeInstruction(
-                tree_ir.LoadLocalInstruction(jit_runtime.LOCALS_EDGE_NAME))))
-
-def with_debug_info_trace(instruction, debug_info, function_name):
-    """Prepends the given instruction with a tracing instruction that prints
-       the given debug information and function name."""
-    if debug_info is None and function_name is None:
-        return instruction
-    else:
-        return tree_ir.create_block(
-            tree_ir.PrintInstruction(
-                tree_ir.LiteralInstruction(
-                    jit_runtime.format_trace_message(
-                        debug_info, function_name,
-                        jit_runtime.BASELINE_JIT_ORIGIN_NAME))),
-            instruction)
-
-class LocalNameMap(object):
-    """A map that converts local variable nodes to identifiers."""
-    def __init__(self, local_mapping=None):
-        if local_mapping is None:
-            local_mapping = {}
-        self.local_mapping = local_mapping
-
-    def get_local_name(self, local_variable_id):
-        """Gets the name for the local variable node with the given id."""
-        if local_variable_id not in self.local_mapping:
-            self.local_mapping[local_variable_id] = 'local%d' % local_variable_id
-        return self.local_mapping[local_variable_id]
-
-class AnalysisState(object):
-    """The state of a bytecode analysis call graph."""
-    def __init__(self, jit, body_id, task_root, local_mapping, max_instructions=None):
-        self.analyzed_instructions = set()
-        self.function_vars = set()
-        self.local_vars = set()
-        self.body_id = body_id
-        self.max_instructions = max_instructions
-        self.task_root = task_root
-        self.jit = jit
-        self.local_name_map = LocalNameMap(local_mapping)
-        self.function_name = jit.jitted_entry_points[body_id]
-        self.enclosing_loop_instruction = None
-
-    def register_local_var(self, local_id):
-        """Registers the given variable node id as a local."""
-        if local_id in self.function_vars:
-            raise jit_runtime.JitCompilationFailedException(
-                "Local is used as target of function call.")
-        self.local_vars.add(local_id)
-
-    def register_function_var(self, local_id):
-        """Registers the given variable node id as a function."""
-        if local_id in self.local_vars:
-            raise jit_runtime.JitCompilationFailedException(
-                "Local is used as target of function call.")
-        self.function_vars.add(local_id)
-
-    def analyze(self, instruction):
-        """Tries to build an intermediate representation from the instruction with the
-        given id."""
-        # Check the analyzed_instructions set for instruction_id to avoid
-        # infinite loops.
-        if instruction in self.analyzed_instructions:
-            raise jit_runtime.JitCompilationFailedException(
-                'Cannot jit non-tree instruction graph.')
-        elif (self.max_instructions is not None and
-              len(self.analyzed_instructions) > self.max_instructions):
-            raise jit_runtime.JitCompilationFailedException(
-                'Maximum number of instructions exceeded.')
-
-        self.analyzed_instructions.add(instruction)
-        instruction_type = type(instruction)
-        if instruction_type in self.instruction_analyzers:
-            # Analyze the instruction itself.
-            outer_result, = yield [
-                ("CALL_ARGS", [self.instruction_analyzers[instruction_type], (self, instruction)])]
-            if instruction.debug_information is not None:
-                if self.jit.tracing_enabled:
-                    outer_result = with_debug_info_trace(
-                        outer_result, instruction.debug_information, self.function_name)
-                if self.jit.source_maps_enabled:
-                    outer_result = tree_ir.DebugInfoInstruction(
-                        outer_result, instruction.debug_information)
-
-            # Check if the instruction has a 'next' instruction.
-            if instruction.next_instruction is None:
-                raise primitive_functions.PrimitiveFinished(outer_result)
-            else:
-                next_result, = yield [
-                    ("CALL_ARGS", [self.analyze, (instruction.next_instruction,)])]
-                raise primitive_functions.PrimitiveFinished(
-                    tree_ir.CompoundInstruction(
-                        outer_result,
-                        next_result))
-        else:
-            raise jit_runtime.JitCompilationFailedException(
-                "Unknown instruction type: '%s'" % type(instruction))
-
-    def analyze_all(self, instruction_ids):
-        """Tries to compile a list of IR trees from the given list of instruction ids."""
-        results = []
-        for inst in instruction_ids:
-            analyzed_inst, = yield [("CALL_ARGS", [self.analyze, (inst,)])]
-            results.append(analyzed_inst)
-
-        raise primitive_functions.PrimitiveFinished(results)
-
-    def analyze_return(self, instruction):
-        """Tries to analyze the given 'return' instruction."""
-        if instruction.value is None:
-            raise primitive_functions.PrimitiveFinished(
-                create_return(
-                    tree_ir.EmptyInstruction()))
-        else:
-            retval, = yield [("CALL_ARGS", [self.analyze, (instruction.value,)])]
-            raise primitive_functions.PrimitiveFinished(
-                create_return(retval))
-
-    def analyze_if(self, instruction):
-        """Tries to analyze the given 'if' instruction."""
-        if instruction.else_clause is None:
-            (cond_r, true_r), = yield [
-                ("CALL_ARGS",
-                 [self.analyze_all,
-                  ([instruction.condition, instruction.if_clause],)])]
-            false_r = tree_ir.EmptyInstruction()
-        else:
-            (cond_r, true_r, false_r), = yield [
-                ("CALL_ARGS",
-                 [self.analyze_all,
-                  ([instruction.condition, instruction.if_clause, instruction.else_clause],)])]
-
-        raise primitive_functions.PrimitiveFinished(
-            tree_ir.SelectInstruction(
-                tree_ir.ReadValueInstruction(cond_r),
-                true_r,
-                false_r))
-
-    def analyze_while(self, instruction):
-        """Tries to analyze the given 'while' instruction."""
-        # Analyze the condition.
-        cond_r, = yield [("CALL_ARGS", [self.analyze, (instruction.condition,)])]
-        # Store the old enclosing loop on the stack, and make this loop the
-        # new enclosing loop.
-        old_loop_instruction = self.enclosing_loop_instruction
-        self.enclosing_loop_instruction = instruction
-        body_r, = yield [("CALL_ARGS", [self.analyze, (instruction.body,)])]
-        # Restore hte old enclosing loop.
-        self.enclosing_loop_instruction = old_loop_instruction
-        if self.jit.nop_insertion_enabled:
-            create_loop_body = lambda check, body: tree_ir.create_block(
-                check,
-                body_r,
-                tree_ir.NopInstruction())
-        else:
-            create_loop_body = tree_ir.CompoundInstruction
-
-        raise primitive_functions.PrimitiveFinished(
-            tree_ir.LoopInstruction(
-                create_loop_body(
-                    tree_ir.SelectInstruction(
-                        tree_ir.ReadValueInstruction(cond_r),
-                        tree_ir.EmptyInstruction(),
-                        tree_ir.BreakInstruction()),
-                    body_r)))
-
-    def analyze_constant(self, instruction):
-        """Tries to analyze the given 'constant' (literal) instruction."""
-        raise primitive_functions.PrimitiveFinished(
-            tree_ir.LiteralInstruction(instruction.constant_id))
-
-    def analyze_output(self, instruction):
-        """Tries to analyze the given 'output' instruction."""
-        value_val, = yield [("CALL_ARGS", [self.analyze, (instruction.value,)])]
-        raise primitive_functions.PrimitiveFinished(create_output(value_val))
-
-    def analyze_input(self, _):
-        """Tries to analyze the given 'input' instruction."""
-        raise primitive_functions.PrimitiveFinished(create_input(self.jit.input_function_enabled))
-
-    def analyze_resolve(self, instruction):
-        """Tries to analyze the given 'resolve' instruction."""
-        # To resolve a variable, we'll do something along the
-        # lines of:
-        #
-        #     if 'local_var' in locals():
-        #         tmp = local_var
-        #     else:
-        #         _globals, = yield [("RD", [task_root, "globals"])]
-        #         global_var, = yield [("RD", [_globals, var_name])]
-        #
-        #         if global_var is None:
-        #             raise Exception("Not found as global: %s" % (var_name))
-        #
-        #         tmp = global_var
-
-        name = self.local_name_map.get_local_name(instruction.variable.node_id)
-
-        if instruction.variable.name is None:
-            raise primitive_functions.PrimitiveFinished(
-                tree_ir.LoadLocalInstruction(name))
-
-        task_root = retrieve_task_root()
-        global_var = tree_ir.StoreLocalInstruction(
-            'global_var',
-            tree_ir.ReadDictionaryValueInstruction(
-                tree_ir.ReadDictionaryValueInstruction(
-                    task_root.create_load(),
-                    tree_ir.LiteralInstruction('globals')),
-                tree_ir.LiteralInstruction(instruction.variable.name)))
-
-        err_block = tree_ir.SelectInstruction(
-            tree_ir.BinaryInstruction(
-                global_var.create_load(),
-                'is',
-                tree_ir.LiteralInstruction(None)),
-            tree_ir.RaiseInstruction(
-                tree_ir.CallInstruction(
-                    tree_ir.LoadGlobalInstruction('Exception'),
-                    [tree_ir.LiteralInstruction(
-                        jit_runtime.GLOBAL_NOT_FOUND_MESSAGE_FORMAT % instruction.variable.name)
-                    ])),
-            tree_ir.EmptyInstruction())
-
-        raise primitive_functions.PrimitiveFinished(
-            tree_ir.SelectInstruction(
-                tree_ir.LocalExistsInstruction(name),
-                tree_ir.LoadLocalInstruction(name),
-                tree_ir.CompoundInstruction(
-                    tree_ir.create_block(
-                        task_root,
-                        global_var,
-                        err_block),
-                    global_var.create_load())))
-
-    def analyze_declare(self, instruction):
-        """Tries to analyze the given 'declare' function."""
-        self.register_local_var(instruction.variable.node_id)
-
-        name = self.local_name_map.get_local_name(instruction.variable.node_id)
-
-        # The following logic declares a local:
-        #
-        #     if 'local_name' not in locals():
-        #         local_name, = yield [("CN", [])]
-        #         yield [("CE", [LOCALS_NODE_NAME, local_name])]
-
-        raise primitive_functions.PrimitiveFinished(
-            tree_ir.SelectInstruction(
-                tree_ir.LocalExistsInstruction(name),
-                tree_ir.EmptyInstruction(),
-                tree_ir.create_new_local_node(
-                    name,
-                    tree_ir.LoadLocalInstruction(jit_runtime.LOCALS_NODE_NAME))))
-
-    def analyze_global(self, instruction):
-        """Tries to analyze the given 'global' (declaration) instruction."""
-        # To declare a variable, we'll do something along the
-        # lines of:
-        #
-        #     _globals, = yield [("RD", [task_root, "globals"])]
-        #     global_var, = yield [("RD", [_globals, var_name])]
-        #
-        #     if global_var is not None:
-        #         yield [("DE", [global_var])]
-        #     global_var, = yield [("CN", [])]
-        #     yield [("CD", [_globals, var_name, global_var])]
-        #
-        #     tmp = global_var
-
-        task_root = retrieve_task_root()
-        _globals = tree_ir.StoreLocalInstruction(
-            '_globals',
-            tree_ir.ReadDictionaryValueInstruction(
-                task_root.create_load(),
-                tree_ir.LiteralInstruction('globals')))
-
-        global_var = tree_ir.StoreLocalInstruction(
-            'global_var',
-            tree_ir.ReadDictionaryEdgeInstruction(
-                _globals.create_load(),
-                tree_ir.LiteralInstruction(instruction.variable.name)))
-
-        raise primitive_functions.PrimitiveFinished(
-            tree_ir.CompoundInstruction(
-                tree_ir.create_block(
-                    task_root,
-                    _globals,
-                    global_var,
-                    tree_ir.SelectInstruction(
-                        tree_ir.BinaryInstruction(
-                            global_var.create_load(),
-                            'is not',
-                            tree_ir.LiteralInstruction(None)),
-                        tree_ir.create_block(
-                            tree_ir.DeleteEdgeInstruction(
-                                global_var.create_load())),
-                        tree_ir.EmptyInstruction()),
-                    global_var.create_store(
-                        tree_ir.CreateNodeInstruction()),
-                    tree_ir.CreateDictionaryEdgeInstruction(
-                        _globals.create_load(),
-                        tree_ir.LiteralInstruction(
-                            instruction.variable.name),
-                        global_var.create_load())),
-                global_var.create_load()))
-
-    def analyze_assign(self, instruction):
-        """Tries to analyze the given 'assign' instruction."""
-        (var_r, value_r), = yield [
-            ("CALL_ARGS", [self.analyze_all, ([instruction.pointer, instruction.value],)])]
-
-        raise primitive_functions.PrimitiveFinished(create_assign(var_r, value_r))
-
-    def analyze_access(self, instruction):
-        """Tries to analyze the given 'access' instruction."""
-        var_r, = yield [("CALL_ARGS", [self.analyze, (instruction.pointer,)])]
-        raise primitive_functions.PrimitiveFinished(create_access(var_r))
-
-    def analyze_direct_call(self, callee_id, callee_name, argument_list):
-        """Tries to analyze a direct 'call' instruction."""
-        body_id, = yield [("RD", [callee_id, jit_runtime.FUNCTION_BODY_KEY])]
-
-        # Make this function dependent on the callee.
-        if body_id in self.jit.compilation_dependencies:
-            self.jit.compilation_dependencies[body_id].add(self.body_id)
-
-        # Figure out if the function might be an intrinsic.
-        intrinsic = self.jit.get_intrinsic(callee_name)
-
-        if intrinsic is None:
-            if callee_name is not None:
-                self.jit.register_global(body_id, callee_name)
-                compiled_func = self.jit.lookup_compiled_function(callee_name)
-            else:
-                compiled_func = None
-
-            if compiled_func is None:
-                # Compile the callee.
-                yield [
-                    ("CALL_ARGS", [self.jit.jit_compile, (self.task_root, body_id, callee_name)])]
-
-            # Get the callee's name.
-            compiled_func_name = self.jit.get_compiled_name(body_id)
-
-            # This handles the corner case where a constant node is called, like
-            # 'call(constant(9), ...)'. In this case, `callee_name` is `None`
-            # because 'constant(9)' doesn't give us a name. However, we can look up
-            # the name of the function at a specific node. If that turns out to be
-            # an intrinsic, then we still want to pick the intrinsic over a call.
-            intrinsic = self.jit.get_intrinsic(compiled_func_name)
-
-        # Analyze the argument dictionary.
-        named_args, = yield [("CALL_ARGS", [self.analyze_arguments, (argument_list,)])]
-
-        if intrinsic is not None:
-            raise primitive_functions.PrimitiveFinished(
-                apply_intrinsic(intrinsic, named_args))
-        else:
-            raise primitive_functions.PrimitiveFinished(
-                tree_ir.create_jit_call(
-                    tree_ir.LoadGlobalInstruction(compiled_func_name),
-                    named_args,
-                    tree_ir.LoadLocalInstruction(jit_runtime.KWARGS_PARAMETER_NAME)))
-
-    def analyze_arguments(self, argument_list):
-        """Analyzes the given parameter-to-value mapping."""
-        named_args = []
-        for param_name, arg in argument_list:
-            param_val, = yield [("CALL_ARGS", [self.analyze, (arg,)])]
-            named_args.append((param_name, param_val))
-
-        raise primitive_functions.PrimitiveFinished(named_args)
-
-    def analyze_indirect_call(self, target, argument_list):
-        """Analyzes a call to an unknown function."""
-        # First off, let's analyze the callee and the argument list.
-        func_val, = yield [("CALL_ARGS", [self.analyze, (target,)])]
-        named_args, = yield [("CALL_ARGS", [self.analyze_arguments, (argument_list,)])]
-        func_val = tree_ir.StoreLocalInstruction(None, func_val)
-        raise primitive_functions.PrimitiveFinished(
-            tree_ir.create_block(
-                func_val,
-                create_indirect_call(func_val.create_load(), named_args)))
-
-    def try_analyze_direct_call(self, target, argument_list):
-        """Tries to analyze the given 'call' instruction as a direct call."""
-        if not self.jit.direct_calls_allowed:
-            raise jit_runtime.JitCompilationFailedException(
-                'Direct calls are not allowed by the JIT.')
-
-        # Figure out what the 'func' instruction's type is.
-        if isinstance(target, bytecode_ir.AccessInstruction):
-            # 'access(resolve(var))' instructions are translated to direct calls.
-            if isinstance(target.pointer, bytecode_ir.ResolveInstruction):
-                self.register_function_var(target.pointer.variable.node_id)
-                resolved_var_name = target.pointer.variable.name
-
-                if self.jit.thunks_enabled:
-                    # Analyze the argument dictionary.
-                    named_args, = yield [("CALL_ARGS", [self.analyze_arguments, (argument_list,)])]
-
-                    # Try to resolve the callee as an intrinsic.
-                    intrinsic = self.jit.get_intrinsic(resolved_var_name)
-                    if intrinsic is not None:
-                        raise primitive_functions.PrimitiveFinished(
-                            apply_intrinsic(intrinsic, named_args))
-
-                    # Otherwise, build a thunk.
-                    thunk_name = self.jit.jit_thunk_global(target.pointer.variable.name)
-                    raise primitive_functions.PrimitiveFinished(
-                        tree_ir.create_jit_call(
-                            tree_ir.LoadGlobalInstruction(thunk_name),
-                            named_args,
-                            tree_ir.LoadLocalInstruction(jit_runtime.KWARGS_PARAMETER_NAME)))
-                else:
-                    # Try to look up the name as a global.
-                    _globals, = yield [("RD", [self.task_root, "globals"])]
-                    global_var, = yield [("RD", [_globals, resolved_var_name])]
-                    global_val, = yield [("RD", [global_var, "value"])]
-
-                    if global_val is not None:
-                        result, = yield [("CALL_ARGS", [self.analyze_direct_call, (
-                            global_val, resolved_var_name, argument_list)])]
-                        raise primitive_functions.PrimitiveFinished(result)
-        elif isinstance(target, bytecode_ir.ConstantInstruction):
-            # 'const(func_id)' instructions are also translated to direct calls.
-            result, = yield [("CALL_ARGS", [self.analyze_direct_call, (
-                target.constant_id, None, argument_list)])]
-            raise primitive_functions.PrimitiveFinished(result)
-
-        raise jit_runtime.JitCompilationFailedException(
-            "Cannot JIT function calls that target an unknown value as direct calls.")
-
-    def analyze_call(self, instruction):
-        """Tries to analyze the given 'call' instruction."""
-        def handle_exception(_):
-            # Looks like we'll have to compile it as an indirect call.
-            gen = self.analyze_indirect_call(instruction.target, instruction.argument_list)
-            result, = yield [("CALL", [gen])]
-            raise primitive_functions.PrimitiveFinished(result)
-
-        # Try to analyze the call as a direct call.
-        yield [("TRY", [])]
-        yield [("CATCH", [jit_runtime.JitCompilationFailedException, handle_exception])]
-        result, = yield [
-            ("CALL_ARGS",
-             [self.try_analyze_direct_call, (instruction.target, instruction.argument_list)])]
-        yield [("END_TRY", [])]
-        raise primitive_functions.PrimitiveFinished(result)
-
-    def analyze_break(self, instruction):
-        """Tries to analyze the given 'break' instruction."""
-        if instruction.loop == self.enclosing_loop_instruction:
-            raise primitive_functions.PrimitiveFinished(tree_ir.BreakInstruction())
-        else:
-            raise jit_runtime.JitCompilationFailedException(
-                "Multilevel 'break' is not supported by the baseline JIT.")
-
-    def analyze_continue(self, instruction):
-        """Tries to analyze the given 'continue' instruction."""
-        if instruction.loop == self.enclosing_loop_instruction:
-            raise primitive_functions.PrimitiveFinished(tree_ir.ContinueInstruction())
-        else:
-            raise jit_runtime.JitCompilationFailedException(
-                "Multilevel 'continue' is not supported by the baseline JIT.")
-
-    instruction_analyzers = {
-        bytecode_ir.SelectInstruction : analyze_if,
-        bytecode_ir.WhileInstruction : analyze_while,
-        bytecode_ir.ReturnInstruction : analyze_return,
-        bytecode_ir.ConstantInstruction : analyze_constant,
-        bytecode_ir.ResolveInstruction : analyze_resolve,
-        bytecode_ir.DeclareInstruction : analyze_declare,
-        bytecode_ir.GlobalInstruction : analyze_global,
-        bytecode_ir.AssignInstruction : analyze_assign,
-        bytecode_ir.AccessInstruction : analyze_access,
-        bytecode_ir.OutputInstruction : analyze_output,
-        bytecode_ir.InputInstruction : analyze_input,
-        bytecode_ir.CallInstruction : analyze_call,
-        bytecode_ir.BreakInstruction : analyze_break,
-        bytecode_ir.ContinueInstruction : analyze_continue
-    }

+ 0 - 98
kernel/modelverse_jit/cfg_data_structures.py

@@ -1,98 +0,0 @@
-"""Defines optimizations that replace Modelverse data structures by Python data structures."""
-
-import modelverse_jit.cfg_ir as cfg_ir
-
-SET_DEF_REWRITE_RULES = {
-    'dict_keys':
-    lambda def_def:
-    def_def.redefine(
-        cfg_ir.DirectFunctionCall(
-            cfg_ir.REVERSE_LIST_MACRO_NAME,
-            [('seq',
-              def_def.insert_before(
-                  cfg_ir.DirectFunctionCall(
-                      cfg_ir.READ_DICT_KEYS_MACRO_NAME,
-                      cfg_ir.get_def_value(def_def).argument_list,
-                      cfg_ir.MACRO_POSITIONAL_CALLING_CONVENTION,
-                      has_side_effects=False)))],
-            cfg_ir.MACRO_POSITIONAL_CALLING_CONVENTION,
-            has_side_effects=False))
-}
-
-def __redefine_as_list_len(use_def, def_def):
-    use_def.redefine(
-        cfg_ir.CreateNode(
-            use_def.insert_before(
-                cfg_ir.DirectFunctionCall(
-                    'len', [('seq', def_def)],
-                    cfg_ir.SIMPLE_POSITIONAL_CALLING_CONVENTION,
-                    has_side_effects=False))))
-
-SET_USE_REWRITE_RULES = {
-    ('set_pop', 'a'):
-    lambda use_def, def_def:
-    use_def.redefine(
-        cfg_ir.DirectFunctionCall(
-            'pop', [('self', def_def)],
-            cfg_ir.SELF_POSITIONAL_CALLING_CONVENTION)),
-    ('list_len', 'a'): __redefine_as_list_len,
-    ('set_len', 'a'): __redefine_as_list_len,
-    ('dict_len', 'a'): __redefine_as_list_len,
-    ('read_nr_out', 'a'): __redefine_as_list_len
-}
-
-def get_call_def_rewriter(definition, def_rewrite_rules):
-    """Gets an appropriate rewrite rule from the given dictionary of call rewrite rules."""
-    if cfg_ir.is_call(definition, calling_convention=cfg_ir.JIT_CALLING_CONVENTION):
-        call = cfg_ir.get_def_value(definition)
-        if call.target_name in def_rewrite_rules:
-            return def_rewrite_rules[call.target_name]
-
-    return None
-
-def get_call_use_rewriter(use_definition, def_definition, use_rewrite_rules):
-    """Gets an appropriate rewrite rule from the given dictionary of call rewrite rules."""
-    if not cfg_ir.is_call(use_definition):
-        return None
-
-    call = cfg_ir.get_def_value(use_definition)
-    if call.calling_convention not in (
-            cfg_ir.JIT_CALLING_CONVENTION,
-            cfg_ir.JIT_NO_GC_CALLING_CONVENTION,
-            cfg_ir.JIT_CFG_INTRINSIC_CALLING_CONVENTION):
-        return None
-
-    for arg_name, arg_def in call.argument_list:
-        if arg_def == def_definition:
-            key = (call.target_name, arg_name)
-            if key in use_rewrite_rules:
-                return use_rewrite_rules[key]
-
-    return None
-
-def apply_rewrite_rules(
-        entry_point,
-        get_def_rewriter,
-        get_use_rewriter):
-    """Applies the given definition and use rewrite rules to all definitions and uses where a
-       rewrite rule can be found for both the definitions and the uses."""
-    # pylint: disable=I0011,W0108
-    cfg_ir.match_and_rewrite(
-        entry_point,
-        lambda def_def:
-        get_def_rewriter(def_def) is not None,
-        lambda use_def, def_def:
-        get_use_rewriter(use_def, def_def) is not None,
-        lambda def_def:
-        get_def_rewriter(def_def)(def_def),
-        lambda use_def, def_def:
-        get_use_rewriter(use_def, def_def)(use_def, def_def))
-
-def optimize_data_structures(entry_point):
-    """Optimizes data structures in the graph defined by the given entry point."""
-    apply_rewrite_rules(
-        entry_point,
-        lambda def_def:
-        get_call_def_rewriter(def_def, SET_DEF_REWRITE_RULES),
-        lambda use_def, def_def:
-        get_call_use_rewriter(use_def, def_def, SET_USE_REWRITE_RULES))

+ 0 - 113
kernel/modelverse_jit/cfg_dominators.py

@@ -1,113 +0,0 @@
-"""Computes dominator trees for control-flow graphs."""
-
-from collections import defaultdict
-import modelverse_jit.cfg_ir as cfg_ir
-
-def sort_postorder(entry_point):
-    """Produces a postorder traversal of the graph with the given block as entry point."""
-    processed = set()
-    results = []
-    def __sort_postorder_step(block):
-        if block in processed:
-            return
-
-        processed.add(block)
-        for branch in block.flow.branches():
-            __sort_postorder_step(branch.block)
-
-        results.append(block)
-
-    __sort_postorder_step(entry_point)
-    return results
-
-class DominatorTree(object):
-    """A data structure that represents a dominator tree."""
-    def __init__(self, immediate_dominators):
-        self.immediate_dominators = immediate_dominators
-        self.dominator_sets = {}
-
-    def get_immediate_dominator(self, block):
-        """Gets the given block's immediate dominator."""
-        return self.immediate_dominators[block]
-
-    def get_dominators(self, block):
-        """Gets the given block's set of all dominators."""
-        if block in self.dominator_sets:
-            return self.dominator_sets
-        else:
-            idom = self.get_immediate_dominator(block)
-            if idom == block:
-                results = set([block])
-            else:
-                results = set(self.get_dominators(idom))
-                results.add(block)
-
-            self.dominator_sets[block] = results
-            return results
-
-    def dominates_block(self, dominator, dominated):
-        """Tests if the first block dominates the second."""
-        return dominator in self.get_dominators(dominated)
-
-    def dominates_instruction(self, dominator, dominated):
-        """Tests if the first instruction dominates the second."""
-        dominator_block = dominator.block
-        dominated_block = dominated.block
-        if dominator_block == dominated_block:
-            return dominator.definition_index < dominated.definition_index
-        else:
-            return self.dominates_block(dominator_block, dominated_block)
-
-# The algorithms below are based on "A Simple, Fast Dominance Algorithm" by
-# Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy
-# (http://www.cs.rice.edu/~keith/Embed/dom.pdf)
-
-def intersect_immediate_dominators(block1, block2, idoms, postorder_nums):
-    """Computes the intersection of the given blocks' immediate dominators."""
-    finger1 = block1
-    finger2 = block2
-    while finger1 != finger2:
-        while postorder_nums[finger1] < postorder_nums[finger2]:
-            finger1 = idoms[finger1]
-
-        while postorder_nums[finger2] < postorder_nums[finger1]:
-            finger2 = idoms[finger2]
-    return finger1
-
-def get_immediate_dominators(entry_point):
-    """Computes the immediate dominators of the control-flow graph defined by the given entry
-       point."""
-    predecessor_map = cfg_ir.get_all_predecessor_blocks(entry_point)
-    idoms = {}
-    postorder_sort = sort_postorder(entry_point)
-    postorder_nums = {}
-    for i, elem in enumerate(postorder_sort):
-        postorder_nums[elem] = i
-        idoms[elem] = None
-
-    idoms[entry_point] = entry_point
-
-    changed = True
-    while changed:
-        changed = False
-        for block in reversed(postorder_sort):
-            if block == entry_point:
-                continue
-
-            new_idom = None
-            for pred in predecessor_map[block]:
-                assert pred in postorder_nums
-                if new_idom is None:
-                    new_idom = pred
-                elif idoms[pred] is not None:
-                    new_idom = intersect_immediate_dominators(pred, new_idom, idoms, postorder_nums)
-
-            if idoms[block] is not new_idom:
-                idoms[block] = new_idom
-                changed = True
-
-    return idoms
-
-def get_dominator_tree(entry_point):
-    """Constructs the dominator tree for the control-flow graph defined by the given entry point."""
-    return DominatorTree(get_immediate_dominators(entry_point))

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1209
kernel/modelverse_jit/cfg_ir.py


+ 0 - 546
kernel/modelverse_jit/cfg_optimization.py

@@ -1,546 +0,0 @@
-"""Optimizes and analyzes CFG-IR."""
-
-from collections import defaultdict
-import modelverse_jit.cfg_ir as cfg_ir
-import modelverse_jit.cfg_dominators as cfg_dominators
-import modelverse_jit.cfg_ssa_construction as cfg_ssa_construction
-import modelverse_jit.cfg_data_structures as cfg_data_structures
-import modelverse_kernel.primitives as primitive_functions
-
-def is_empty_block(block):
-    """Tests if the given block contains no parameters or definitions."""
-    return len(block.parameters) == 0 and len(block.definitions) == 0
-
-def optimize_flow(block):
-    """Optimizes the given block's flow instruction."""
-    changed = True
-    while changed:
-        changed = False
-
-        # Select flow with a literal condition can be optimized to a direct jump.
-        if (isinstance(block.flow, cfg_ir.SelectFlow)
-                and cfg_ir.is_literal_def(block.flow.condition)):
-            literal = cfg_ir.get_literal_def_value(block.flow.condition)
-            block.flow = cfg_ir.JumpFlow(
-                block.flow.if_branch if literal else block.flow.else_branch)
-            changed = True
-
-        # Jumps to blocks which contain no parameters or definitions can be replaced
-        # by the target block's flow.
-        if (isinstance(block.flow, cfg_ir.JumpFlow)
-                and is_empty_block(block.flow.branch.block)
-                and block.flow.branch.block is not block):
-            block.flow = block.flow.branch.block.flow
-            changed = True
-
-        # Branches to blocks which contain nothing but a jump can be replaced by branches
-        # to the jump's target.
-        for branch in block.flow.branches():
-            if (is_empty_block(branch.block)
-                    and branch.block is not block
-                    and isinstance(branch.block.flow, cfg_ir.JumpFlow)):
-                new_branch = branch.block.flow.branch
-                branch.block = new_branch.block
-                branch.arguments = new_branch.arguments
-                changed = True
-
-def optimize_graph_flow(entry_point):
-    """Optimizes all flow instructions in the graph defined by the given entry point."""
-    for block in cfg_ir.get_all_blocks(entry_point):
-        optimize_flow(block)
-
-def merge_blocks(entry_point):
-    """Merges blocks which have exactly one predecessor with said predecessor, if the
-       predecessor has a jump flow instruction."""
-    predecessor_map = cfg_ir.get_all_predecessor_blocks(entry_point)
-    queue = set(predecessor_map.keys())
-    queue.add(entry_point)
-    def __do_merge(source, target):
-        target_params = list(target.parameters)
-        branch_args = list(source.flow.branch.arguments)
-        for target_param, branch_arg in zip(target_params, branch_args):
-            target.remove_parameter(target_param)
-            target_param.redefine(branch_arg)
-            source.append_definition(target_param)
-
-        target_defs = list(target.definitions)
-        for target_def in target_defs:
-            target.remove_definition(target_def)
-            source.append_definition(target_def)
-
-        source.flow = target.flow
-        for preds in list(predecessor_map.values()):
-            if target in preds:
-                preds[preds.index(target)] = source
-                # preds.remove(target)
-                # preds.add(source)
-
-    while len(queue) > 0:
-        block = queue.pop()
-        if isinstance(block.flow, cfg_ir.JumpFlow):
-            next_block = block.flow.branch.block
-            preds = predecessor_map[next_block]
-            if (len(preds) == 1
-                    and next(iter(preds)) == block
-                    and block != next_block
-                    and next_block != entry_point):
-                __do_merge(block, next_block)
-                del predecessor_map[next_block]
-                queue.add(block)
-                if next_block in queue:
-                    queue.remove(next_block)
-
-def elide_local_checks(entry_point):
-    """Tries to elide redundant checks on local variables."""
-    # The plan here is to replace all check-local-exists defs by literals if
-    # they are either dominated by an appropriate declare-local or not reachable
-    # from a declare-local.
-    local_checks = []
-    local_defs = defaultdict(list)
-    for block in cfg_ir.get_all_blocks(entry_point):
-        for definition in block.definitions:
-            def_value = definition.value
-            if isinstance(def_value, cfg_ir.CheckLocalExists):
-                local_checks.append((def_value.variable.node_id, definition))
-            elif isinstance(def_value, cfg_ir.DeclareLocal):
-                local_defs[def_value.variable.node_id].append(definition)
-
-    dominator_tree = cfg_dominators.get_dominator_tree(entry_point)
-    reachable_blocks = cfg_ir.get_all_reachable_blocks(entry_point)
-    for (variable, check) in local_checks:
-        is_reachable = False
-        for local_def in local_defs[variable]:
-            if dominator_tree.dominates_instruction(local_def, check):
-                # Check is dominated by a definition. Replace it by a 'True' literal.
-                check.redefine(cfg_ir.Literal(True))
-                is_reachable = True
-                break
-            elif check.block in reachable_blocks[local_def.block]:
-                is_reachable = True
-
-        if not is_reachable:
-            # Check cannot be reached from any definition. Replace it by a 'False' literal.
-            check.redefine(cfg_ir.Literal(False))
-
-def eliminate_unused_definitions(entry_point):
-    """Tries to eliminate unused definitions in the control-flow graphb defined by the
-       given entry point."""
-    def_dependencies = defaultdict(set)
-    root_defs = set()
-    # Gather dependencies.
-    for block in cfg_ir.get_all_blocks(entry_point):
-        for definition in block.parameters + block.definitions:
-            all_dependencies = list(definition.get_all_dependencies())
-            def_dependencies[definition].update(
-                [dep for dep in all_dependencies
-                 if isinstance(dep, cfg_ir.Definition)])
-
-            if len(all_dependencies) > 0 and definition.has_bidirectional_dependencies():
-                for dep in all_dependencies:
-                    def_dependencies[dep].add(definition)
-
-            if definition.has_side_effects():
-                root_defs.add(definition)
-
-        for dep in block.flow.get_dependencies():
-            if isinstance(dep, cfg_ir.Definition):
-                root_defs.add(dep)
-            else:
-                assert isinstance(dep, cfg_ir.Branch)
-                for param, arg in zip(dep.block.parameters, dep.arguments):
-                    def_dependencies[param].add(arg)
-
-    # Figure out which definitions are live.
-    live_defs = set()
-    def __mark_live(definition):
-        if definition in live_defs:
-            return
-
-        live_defs.add(definition)
-        if definition in def_dependencies:
-            for dep in def_dependencies[definition]:
-                __mark_live(dep)
-
-    for root in root_defs:
-        __mark_live(root)
-
-    # Remove all dead definitions.
-    dead_defs = set.difference(set(def_dependencies.keys()), live_defs)
-    dead_phis = set()
-    for dead_def in dead_defs:
-        if isinstance(dead_def.value, cfg_ir.BlockParameter):
-            dead_phis.add(dead_def)
-        else:
-            dead_def.block.remove_definition(dead_def)
-
-    erase_parameters(entry_point, dead_phis)
-
-def eliminate_trivial_phis(entry_point):
-    """Eliminates trivial block parameters, i.e., block parameters which are really
-       aliases."""
-    phi_values = defaultdict(set)
-    all_blocks = list(cfg_ir.get_all_blocks(entry_point))
-    for block in all_blocks:
-        for branch in block.flow.branches():
-            for phi, arg in zip(branch.block.parameters, branch.arguments):
-                phi_values[phi].add(arg)
-
-    replacements = []
-    for block in all_blocks:
-        block_parameters = list(block.parameters)
-        for parameter_def in block_parameters:
-            trivial_phi_val = cfg_ir.get_trivial_phi_value(
-                parameter_def, phi_values[parameter_def])
-            if trivial_phi_val is not None:
-                replacements.append((parameter_def, trivial_phi_val))
-
-    erase_parameters(entry_point, set([parameter_def for parameter_def, _ in replacements]))
-
-    for parameter_def, trivial_phi_val in replacements:
-        block = parameter_def.block
-        parameter_def.redefine(trivial_phi_val)
-        block.prepend_definition(parameter_def)
-
-def erase_parameters(entry_point, parameters_to_erase):
-    """Erases all arguments for the given set of parameters, and then takes out the
-       parameters themselves."""
-    for block in cfg_ir.get_all_blocks(entry_point):
-        for branch in block.flow.branches():
-            new_arg_list = []
-            for parameter, arg in zip(branch.block.parameters, branch.arguments):
-                if parameter not in parameters_to_erase:
-                    new_arg_list.append(arg)
-            branch.arguments = new_arg_list
-
-    for parameter_def in parameters_to_erase:
-        parameter_def.block.remove_parameter(parameter_def)
-
-def apply_cfg_intrinsic(intrinsic_function, original_definition, named_args):
-    """Applies the given intrinsic to the given sequence of named arguments."""
-    kwargs = dict(named_args)
-    kwargs['original_def'] = original_definition
-    return intrinsic_function(**kwargs)
-
-def try_redefine_as_direct_call(definition, jit, called_globals):
-    """Tries to redefine the given indirect call definition as a direct call."""
-    call = cfg_ir.get_def_value(definition)
-    if not isinstance(call, cfg_ir.IndirectFunctionCall):
-        return
-
-    target = cfg_ir.get_def_value(call.target)
-    if isinstance(target, cfg_ir.LoadPointer):
-        loaded_ptr = cfg_ir.get_def_value(target.pointer)
-        if isinstance(loaded_ptr, cfg_ir.ResolveGlobal):
-            resolved_var_name = loaded_ptr.variable.name
-            called_globals.add(loaded_ptr)
-
-            # Try to resolve the callee as an intrinsic.
-            intrinsic = jit.get_cfg_intrinsic(resolved_var_name)
-            if intrinsic is not None:
-                definition.redefine(
-                    cfg_ir.DirectFunctionCall(
-                        resolved_var_name, call.argument_list,
-                        cfg_ir.JIT_CFG_INTRINSIC_CALLING_CONVENTION))
-            else:
-                # Otherwise, build a thunk.
-                thunk_name = jit.jit_thunk_global(resolved_var_name)
-                calling_convention = (
-                    cfg_ir.JIT_NO_GC_CALLING_CONVENTION
-                    if jit.get_intrinsic(thunk_name) is not None
-                    else cfg_ir.JIT_CALLING_CONVENTION)
-                definition.redefine(
-                    cfg_ir.DirectFunctionCall(
-                        thunk_name, call.argument_list, calling_convention))
-                called_globals.add(loaded_ptr)
-    elif isinstance(target, cfg_ir.Literal):
-        node_id = target.literal
-        if target.literal is None:
-            raise Exception("NONE")
-        thunk_name = jit.jit_thunk_constant_function(node_id)
-        definition.redefine(
-            cfg_ir.DirectFunctionCall(
-                thunk_name, call.argument_list, cfg_ir.JIT_CALLING_CONVENTION))
-
-def get_checked_global(definition):
-    """If the definition is a check that tests if a global does not exist, then
-       the instruction that resolves the global is returned; otherwise None."""
-    def_value = cfg_ir.get_def_value(definition)
-    if not isinstance(def_value, cfg_ir.Binary):
-        return None
-
-    if def_value.operator != 'is':
-        return None
-
-    def __get_checked_global_single_dir(lhs, rhs):
-        if (isinstance(lhs, cfg_ir.ResolveGlobal)
-                and isinstance(rhs, cfg_ir.Literal)
-                and rhs.literal is None):
-            return lhs
-        else:
-            return None
-
-    bin_lhs = cfg_ir.get_def_value(def_value.lhs)
-    bin_rhs = cfg_ir.get_def_value(def_value.rhs)
-    result = __get_checked_global_single_dir(bin_lhs, bin_rhs)
-    if result is None:
-        result = __get_checked_global_single_dir(bin_rhs, bin_lhs)
-
-    return result
-
-def optimize_calls(entry_point, jit):
-    """Converts indirect calls to direct calls in the control-flow graph defined by the
-       given entry point."""
-    called_globals = set()
-    global_exists_defs = defaultdict(list)
-    for block in cfg_ir.get_all_blocks(entry_point):
-        for definition in block.definitions:
-            checked_global = get_checked_global(definition)
-            if checked_global is not None:
-                global_exists_defs[checked_global].append(definition)
-            else:
-                try_redefine_as_direct_call(definition, jit, called_globals)
-
-    for resolve_global in called_globals:
-        for exists_def in global_exists_defs[resolve_global]:
-            exists_def.redefine(cfg_ir.Literal(False))
-
-def expand_cfg_intrinsics(entry_point, jit):
-    """Expands CFG JIT intrinsics in the control-flow graph defined by the given entry point."""
-    for block in cfg_ir.get_all_blocks(entry_point):
-        for definition in block.definitions:
-            def_value = definition.value
-            if (isinstance(def_value, cfg_ir.DirectFunctionCall)
-                    and def_value.calling_convention ==
-                    cfg_ir.JIT_CFG_INTRINSIC_CALLING_CONVENTION):
-                intrinsic = jit.get_cfg_intrinsic(def_value.target_name)
-                apply_cfg_intrinsic(intrinsic, definition, def_value.argument_list)
-
-def simplify_values(entry_point):
-    """Simplifies values in the control-flow graph defined by the given entry point."""
-    for block in cfg_ir.get_all_blocks(entry_point):
-        for definition in block.definitions:
-            def_val = cfg_ir.get_def_value(definition)
-            if isinstance(def_val, cfg_ir.Read):
-                read_node = cfg_ir.get_def_value(def_val.node)
-                if isinstance(read_node, cfg_ir.CreateNode):
-                    definition.redefine(read_node.value)
-            elif isinstance(def_val, cfg_ir.Binary):
-                lhs = cfg_ir.get_def_value(def_val.lhs)
-                rhs = cfg_ir.get_def_value(def_val.rhs)
-                if isinstance(lhs, cfg_ir.Literal) and isinstance(rhs, cfg_ir.Literal):
-                    definition.redefine(
-                        cfg_ir.Literal(
-                            eval('%r %s %r' % (lhs.literal, def_val.operator, rhs.literal))))
-            elif isinstance(def_val, cfg_ir.Unary):
-                operand = cfg_ir.get_def_value(def_val.operand)
-                if isinstance(operand, cfg_ir.Literal):
-                    definition.redefine(
-                        cfg_ir.Literal(
-                            eval('%s %r' % (def_val.operator, operand.literal))))
-
-def inline_constants(entry_point):
-    """Replaces reads of constant nodes by the literals they contain."""
-    for block in cfg_ir.get_all_blocks(entry_point):
-        for definition in block.definitions:
-            def_val = cfg_ir.get_def_value(definition)
-            if isinstance(def_val, cfg_ir.Read):
-                read_node = cfg_ir.get_def_value(def_val.node)
-                if isinstance(read_node, cfg_ir.Literal):
-                    val, = yield [("RV", [read_node.literal])]
-                    definition.redefine(cfg_ir.Literal(val))
-
-def expand_indirect_definitions(entry_point):
-    """Replaces indirect definitions by the values referred to by those definitions."""
-    def __expand_indirect_defs(value):
-        dependencies = value.get_dependencies()
-        if len(dependencies) == 0:
-            return value
-        else:
-            new_dependencies = []
-            for dep in dependencies:
-                new_dep = dep
-                if isinstance(new_dep, cfg_ir.Definition):
-                    while isinstance(new_dep.value, cfg_ir.Definition):
-                        new_dep = new_dep.value
-                else:
-                    new_dep = __expand_indirect_defs(new_dep)
-
-                new_dependencies.append(new_dep)
-            return value.create(new_dependencies)
-
-    for block in cfg_ir.get_all_blocks(entry_point):
-        block_definitions = list(block.definitions)
-        for definition in block_definitions:
-            if isinstance(definition.value, cfg_ir.Definition):
-                block.remove_definition(definition)
-            else:
-                definition.redefine(
-                    __expand_indirect_defs(definition.value))
-
-        block.flow = __expand_indirect_defs(block.flow)
-
-def optimize_reads(entry_point):
-    """Tries to replace repeated reads by a single read."""
-    cfg_ir.match_and_rewrite(
-        entry_point,
-        lambda _: True,
-        lambda use_def, _: cfg_ir.is_value_def(use_def, cfg_ir.Read),
-        lambda def_def:
-        def_def.redefine(
-            cfg_ir.Read(def_def.insert_before(def_def.value))),
-        lambda use_def, def_def: use_def.redefine(def_def))
-
-def protect_from_gc(entry_point):
-    """Protects locals in the control-flow graph defined by the given
-       entry point from the GC."""
-    root_node = entry_point.prepend_definition(cfg_ir.AllocateRootNode())
-    def protect_def_from_gc(definition):
-        """Protects the given definition from the GC."""
-        definition.insert_after(cfg_ir.create_gc_protect(definition, root_node))
-
-    def maybe_protect_def_from_gc(definition):
-        """Protects the given definition from the GC, if its result is not None."""
-        definition.insert_after(cfg_ir.create_conditional_gc_protect(definition, root_node))
-
-    for block in cfg_ir.get_all_blocks(entry_point):
-        for definition in block.definitions:
-            def_value = cfg_ir.get_def_value(definition)
-            if isinstance(def_value, cfg_ir.CreateNode):
-                protect_def_from_gc(definition)
-            elif (isinstance(def_value, cfg_ir.IndirectFunctionCall)
-                  or (isinstance(def_value, cfg_ir.DirectFunctionCall)
-                      and (def_value.calling_convention == cfg_ir.JIT_CALLING_CONVENTION
-                           or def_value.calling_convention == cfg_ir.JIT_NO_GC_CALLING_CONVENTION
-                           or def_value.calling_convention == cfg_ir.MACRO_IO_CALLING_CONVENTION)
-                      and def_value.has_value())):
-                maybe_protect_def_from_gc(definition)
-
-        if isinstance(block.flow, (cfg_ir.ReturnFlow, cfg_ir.ThrowFlow)):
-            block.append_definition(cfg_ir.DeallocateRootNode(root_node))
-
-def elide_gc_protects(entry_point):
-    """Tries to elide GC protection values."""
-    # We don't need to protect a value from the GC if it is used for the
-    # last time _before_ the GC has an opportunity to kick in. To simplify
-    # things, we'll do a quick block-based analysis.
-    def __may_cause_gc(definition):
-        def_value = cfg_ir.get_def_value(definition)
-        if isinstance(def_value, cfg_ir.IndirectFunctionCall):
-            return True
-        elif (isinstance(def_value, cfg_ir.DirectFunctionCall)
-              and (def_value.calling_convention == cfg_ir.JIT_CALLING_CONVENTION
-                   or def_value.calling_convention == cfg_ir.MACRO_IO_CALLING_CONVENTION)):
-            return True
-        else:
-            return False
-
-    def __get_protected_def(def_or_value):
-        value = cfg_ir.get_def_value(def_or_value)
-        if cfg_ir.is_call(
-                value, target_name=cfg_ir.GC_PROTECT_MACRO_NAME,
-                calling_convention=cfg_ir.MACRO_POSITIONAL_CALLING_CONVENTION):
-            _, protected_def = value.argument_list[0]
-            return protected_def
-        elif cfg_ir.is_call(
-                value, target_name=cfg_ir.MAYBE_GC_PROTECT_MACRO_NAME,
-                calling_convention=cfg_ir.MACRO_POSITIONAL_CALLING_CONVENTION):
-            _, protected_def = value.argument_list[1]
-            return protected_def
-        else:
-            return None
-
-    def_blocks = {}
-    def __register_def_or_use(definition, block):
-        if definition in def_blocks and def_blocks[definition] != block:
-            # Definition seems to be used across basic blocks.
-            ineligible_defs.add(definition)
-
-        def_blocks[definition] = block
-
-    ineligible_defs = set()
-    def_protections = defaultdict(list)
-    for block in cfg_ir.get_all_blocks(entry_point):
-        no_gc_defs = set()
-        block_defs = set()
-        first_gc = {}
-        last_def_uses = {}
-        for i, definition in enumerate(block.definitions):
-            if isinstance(definition.value, cfg_ir.Definition):
-                # Handling definitions of definitions is complicated and they should already have
-                # been expanded at this point. Just mark them as ineligible.
-                ineligible_defs.add(definition)
-                ineligible_defs.add(definition.value)
-                continue
-
-            protected_def = __get_protected_def(definition)
-            if protected_def is not None:
-                # We just ran into a gc_protect/maybe_gc_protect.
-                def_protections[protected_def].append(definition)
-                continue
-
-            block_defs.add(definition)
-            __register_def_or_use(definition, block)
-
-            for dependency in definition.get_all_dependencies():
-                __register_def_or_use(dependency, block)
-                last_def_uses[dependency] = i
-
-            if __may_cause_gc(definition):
-                for gc_def in no_gc_defs:
-                    first_gc[gc_def] = i
-                no_gc_defs = set()
-
-            no_gc_defs.add(definition)
-
-        # Mark all branch arguments as ineligible.
-        for branch in block.flow.branches():
-            ineligible_defs.update(branch.arguments)
-
-        for dependency in block.flow.get_dependencies():
-            last_def_uses[dependency] = None
-
-        for definition in block_defs:
-            if definition in ineligible_defs:
-                # Definition was already ineligible.
-                continue
-
-            # Mark `definition` as ineligible if there is a GC definition in the range of
-            # definitions (definition, last_def_uses[definition]].
-            if definition in first_gc:
-                if definition in last_def_uses:
-                    last_use = last_def_uses[definition]
-                    if last_use is None or first_gc[definition] <= last_use:
-                        ineligible_defs.add(definition)
-
-    # Elide all GC protections for definitions which are not in the `ineligible_defs` set.
-    for protected, protections in list(def_protections.items()):
-        if protected not in ineligible_defs:
-            for protect_def in protections:
-                protect_def.redefine(cfg_ir.Literal(None))
-
-def optimize(entry_point, jit):
-    """Optimizes the control-flow graph defined by the given entry point.
-       A potentially altered entry point is returned."""
-    optimize_graph_flow(entry_point)
-    elide_local_checks(entry_point)
-    optimize_graph_flow(entry_point)
-    merge_blocks(entry_point)
-    eliminate_trivial_phis(entry_point)
-    entry_point = cfg_ssa_construction.construct_ssa_form(entry_point)
-    if jit.direct_calls_allowed:
-        optimize_calls(entry_point, jit)
-    cfg_data_structures.optimize_data_structures(entry_point)
-    expand_cfg_intrinsics(entry_point, jit)
-    yield [("CALL_ARGS", [inline_constants, (entry_point,)])]
-    optimize_reads(entry_point)
-    simplify_values(entry_point)
-    eliminate_unused_definitions(entry_point)
-    optimize_graph_flow(entry_point)
-    expand_indirect_definitions(entry_point)
-    eliminate_unused_definitions(entry_point)
-    merge_blocks(entry_point)
-    expand_indirect_definitions(entry_point)
-    protect_from_gc(entry_point)
-    elide_gc_protects(entry_point)
-    eliminate_unused_definitions(entry_point)
-    raise primitive_functions.PrimitiveFinished(entry_point)

+ 0 - 268
kernel/modelverse_jit/cfg_ssa_construction.py

@@ -1,268 +0,0 @@
-"""Converts 'declare-local', 'load' and 'store' instructions into SSA form."""
-
-from collections import defaultdict
-import modelverse_jit.cfg_ir as cfg_ir
-
-def get_local_id(def_or_value):
-    """Gets the node of the local resolved or declared by the given definition or value.
-       If the given definition or value does not refer to a 'resolve-local' or
-       'declare-local' node, then None is returned."""
-    value = cfg_ir.get_def_value(def_or_value)
-    if isinstance(value, (cfg_ir.ResolveLocal, cfg_ir.DeclareLocal)):
-        return value.variable.node_id
-    else:
-        return None
-
-def get_ineligible_local_ids(entry_point):
-    """Finds the ids of all local variables which are not eligible for conversion to SSA form."""
-    # Local variables are eligible for conversion to SSA form if their pointer node is never
-    # leaked to the outside world. So we know that we can safely convert a local to SSA form
-    # if 'resolve-local' values are only used by 'load' and 'store' values.
-    ineligible_local_ids = set()
-    def __maybe_mark_ineligible(def_or_value):
-        local_id = get_local_id(def_or_value)
-        if local_id is not None:
-            ineligible_local_ids.add(local_id)
-
-    for block in cfg_ir.get_all_blocks(entry_point):
-        for definition in block.definitions + [block.flow]:
-            value = cfg_ir.get_def_value(definition)
-            if isinstance(value, cfg_ir.LoadPointer):
-                # Loading a pointer to a local is fine.
-                pass
-            elif isinstance(value, cfg_ir.StoreAtPointer):
-                # Storing a value in a local is fine, too.
-                # But be careful not to ignore a store where the stored value is a local pointer.
-                __maybe_mark_ineligible(value.value)
-            else:
-                # Walk over the dependencies, and mark them all as ineligible for
-                # local-to-SSA conversion.
-                for dependency in value.get_all_dependencies():
-                    __maybe_mark_ineligible(dependency)
-
-    return ineligible_local_ids
-
-def construct_ssa_form(entry_point):
-    """Converts local variables into SSA form in the graph defined by the given entry point.
-       A potentially new entry block is returned."""
-    # Build some helper data structures.
-    all_blocks = list(cfg_ir.get_all_blocks(entry_point))
-    ineligible_locals = get_ineligible_local_ids(entry_point)
-    predecessor_map = cfg_ir.get_all_predecessor_blocks(entry_point)
-
-    # Create the SSA construction state.
-    state = SSAConstructionState(all_blocks, ineligible_locals, predecessor_map)
-
-    # Fill all blocks in the graph.
-    for block in all_blocks:
-        state.fill_block(block)
-
-    # Update branches.
-    for block in all_blocks:
-        state.update_block_branches(block)
-
-    # Nullify entry point parameters.
-    return nullify_entry_block_parameters(entry_point)
-
-def nullify_entry_block_parameters(entry_point):
-    """Creates or returns an entry block that takes no parameters.
-       The (new) entry block is returned."""
-    # The SSA construction algorithm has the nasty habit of replacing potentially
-    # undefined variables by entry block parameters. Codegen doesn't like that one
-    # bit: it assumes that all block parameters are defined by the branches to those
-    # parameters -- but there usually is no branch to the entry point!
-    #
-    # We can fix this by either replacing the block-parameters in the entry block by
-    # definitions, or by creating a new entry point that jumps to the old entry
-    # point with an argument list. The former construction is more efficient, but it is only
-    # correct if there are no pre-existing branches to the entry point.
-    #
-    # We could build the predecessor map block and use the first option if possible,
-    # but we won't; trivial phi elimination followed by block merging will reduce
-    # the second construction to the first one anyway.
-    if len(entry_point.parameters) == 0:
-        return entry_point
-
-    pre_entry_point = cfg_ir.BasicBlock(entry_point.counter)
-    arg_list = []
-    for _ in entry_point.parameters:
-        literal_def = pre_entry_point.append_definition(cfg_ir.Literal(None))
-        arg_list.append(literal_def)
-
-    pre_entry_point.flow = cfg_ir.create_jump(entry_point, arg_list)
-    return pre_entry_point
-
-# The algorithms below are based on
-# Simple and Efficient Construction of Static Single Assignment Form by M. Braun et al
-# (https://pp.info.uni-karlsruhe.de/uploads/publikationen/braun13cc.pdf).
-
-class SSAConstructionState(object):
-    """Encapsulates state related to SSA construction."""
-    def __init__(self, all_blocks, ineligible_locals, predecessor_map):
-        self.all_blocks = all_blocks
-        self.ineligible_locals = ineligible_locals
-        self.predecessor_map = predecessor_map
-        # `current_defs` is a local node id -> basic block -> definition map.
-        self.current_defs = defaultdict(dict)
-        # `incomplete_phis` is a basic block -> local node id -> block parameter def map.
-        self.incomplete_phis = defaultdict(dict)
-        # `extra_phi_operands` is a basic block -> block parameter def -> def map.
-        self.extra_phi_operands = defaultdict(dict)
-        self.processed_blocks = set()
-        self.filled_blocks = set()
-        self.sealed_blocks = set()
-
-    def read_variable(self, block, node_id):
-        """Reads the latest definition of the local variable with the
-           given node id for the specified block."""
-        if block in self.current_defs[node_id]:
-            return self.current_defs[node_id][block]
-        else:
-            return self.read_variable_recursive(block, node_id)
-
-    def write_variable(self, block, node_id, value):
-        """Writes the given value to the local with the specified id in the
-           specified block."""
-        self.current_defs[node_id][block] = value
-
-    def read_variable_recursive(self, block, node_id):
-        """Reads the latest definition of the local variable with the
-           given node id from one of the given block's predecessor blocks."""
-        if block not in self.sealed_blocks:
-            # Create an incomplete phi.
-            val = block.append_parameter(cfg_ir.BlockParameter())
-            self.incomplete_phis[block][node_id] = val
-        elif len(self.predecessor_map[block]) == 1:
-            # Optimize the common case of one predecessor: no phi needed.
-            pred = next(iter(self.predecessor_map[block]))
-            val = self.read_variable(pred, node_id)
-        else:
-            # Break potential cycles with an operandless phi.
-            val = block.append_parameter(cfg_ir.BlockParameter())
-            self.write_variable(block, node_id, val)
-            val = self.add_phi_operands(node_id, val)
-
-        self.write_variable(block, node_id, val)
-        return val
-
-    def add_phi_operands(self, node_id, phi_def):
-        """Finds out which arguments branches should provide for the given block
-           parameter definition."""
-        # Determine operands from predecessors
-        all_values = []
-        for pred in self.predecessor_map[phi_def.block]:
-            arg = self.read_variable(pred, node_id)
-            self.extra_phi_operands[pred][phi_def] = arg
-            all_values.append(arg)
-        return self.try_remove_trivial_phi(phi_def, all_values)
-
-    def try_remove_trivial_phi(self, phi_def, values):
-        """Tries to remove a trivial block parameter definition."""
-        # This is a somewhat simplified (and less powerful) version of the
-        # algorithm in the SSA construction paper. That's kind of okay, though;
-        # trivial phi elimination is also implemented as a separate pass in the
-        # optimization pipeline.
-        trivial_phi_val = cfg_ir.get_trivial_phi_value(phi_def, values)
-        if trivial_phi_val is None:
-            return phi_def
-        else:
-            for pred in self.predecessor_map[phi_def.block]:
-                del self.extra_phi_operands[pred][phi_def]
-
-            phi_def.block.remove_parameter(phi_def)
-            phi_def.redefine(trivial_phi_val)
-            phi_def.block.prepend_definition(phi_def)
-            return trivial_phi_val
-
-    def has_sealed(self, block):
-        """Tells if the given block has been sealed yet."""
-        return block in self.sealed_blocks
-
-    def can_seal(self, block):
-        """Tells if the given block can be sealed right away."""
-        # A block can be sealed if all if its predecessors have been filled.
-        return all(
-            [predecessor in self.filled_blocks for predecessor in self.predecessor_map[block]])
-
-    def seal_all_sealable_blocks(self):
-        """Seals all sealable blocks."""
-        for block in self.all_blocks:
-            if self.can_seal(block):
-                self.seal_block(block)
-
-    def seal_block(self, block):
-        """Seals the given block."""
-        if self.has_sealed(block):
-            return
-
-        for node_id, phi_def in list(self.incomplete_phis[block].items()):
-            self.add_phi_operands(node_id, phi_def)
-
-        self.sealed_blocks.add(block)
-
-    def has_filled(self, block):
-        """Tells if the given block has been filled yet."""
-        return block in self.filled_blocks
-
-    def fill_block(self, block):
-        """Visits all definitions in the given block. Locals are converted into SSA form."""
-        if block in self.processed_blocks:
-            return
-
-        self.processed_blocks.add(block)
-
-        # Try to seal the block right away if at all possible.
-        if self.can_seal(block):
-            self.seal_block(block)
-
-        block_definitions = list(block.definitions)
-        for definition in block_definitions:
-            value = definition.value
-            if cfg_ir.is_value_def(value, cfg_ir.LoadPointer):
-                # Read the variable from the definitions dictionary.
-                node_id = get_local_id(value.pointer)
-                if node_id is not None and node_id not in self.ineligible_locals:
-                    definition.redefine(self.read_variable(block, node_id))
-            elif isinstance(value, cfg_ir.StoreAtPointer):
-                node_id = get_local_id(value.pointer)
-                if node_id is not None and node_id not in self.ineligible_locals:
-                    # Write to the variable, and replace the definition by a 'None' literal.
-                    self.write_variable(block, node_id, value.value)
-                    definition.redefine(cfg_ir.Literal(None))
-            elif isinstance(value, cfg_ir.DeclareLocal):
-                node_id = value.variable.node_id
-                if node_id not in self.ineligible_locals:
-                    definition.redefine(cfg_ir.Literal(None))
-
-
-        # Mark the block as filled.
-        self.filled_blocks.add(block)
-
-        # Seal all sealable blocks.
-        self.seal_all_sealable_blocks()
-
-        # Fill successor blocks.
-        for branch in block.flow.branches():
-            self.fill_block(branch.block)
-
-    def update_block_branches(self, block):
-        """Appends arguments to the given block's flow instruction's branches, if necessary."""
-        for branch in block.flow.branches():
-            # Find all pairs phis which are defined in the branch target block.
-            applicable_pairs = [
-                (phi_def, operand_def)
-                for phi_def, operand_def in list(self.extra_phi_operands[block].items())
-                if phi_def.block == branch.block]
-
-            if len(applicable_pairs) == 0:
-                # We might as well early-out here.
-                continue
-
-            # Sort the pairs by block parameter index.
-            sorted_pairs = sorted(
-                applicable_pairs,
-                key=lambda phi_def: phi_def[0].block.parameters.index(phi_def[0]))
-
-            # Append arguments to the branch.
-            for _, arg in sorted_pairs:
-                branch.arguments.append(arg)

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1021
kernel/modelverse_jit/cfg_to_tree.py


+ 0 - 500
kernel/modelverse_jit/intrinsics.py

@@ -1,500 +0,0 @@
-import time
-import modelverse_jit.jit as jit
-import modelverse_jit.tree_ir as tree_ir
-import modelverse_jit.cfg_ir as cfg_ir
-import modelverse_jit.runtime as jit_runtime
-
-BINARY_INTRINSICS = {
-    'value_eq' : '==',
-    'value_neq' : '!=',
-
-    'bool_and' : 'and',
-    'bool_or' : 'or',
-
-    'integer_addition' : '+',
-    'integer_subtraction' : '-',
-    'integer_multiplication' : '*',
-    'integer_division' : '/',
-    'integer_gt' : '>',
-    'integer_gte' : '>=',
-    'integer_lt' : '<',
-    'integer_lte' : '<=',
-
-    'float_addition' : '+',
-    'float_subtraction' : '-',
-    'float_multiplication' : '*',
-    'float_division' : '/',
-    'float_gt' : '>',
-    'float_gte' : '>=',
-    'float_lt' : '<',
-    'float_lte' : '<='
-}
-
-UNARY_INTRINSICS = {
-    'bool_not' : 'not',
-    'integer_neg' : '-',
-    'float_neg' : '-'
-}
-
-CAST_INTRINSICS = {
-    'cast_float' : float,
-    'cast_string' : str,
-    'cast_boolean' : bool,
-    'cast_integer' : int,
-}
-
-def create_get_length(expression):
-    """Creates an expression that evaluates the given expression, and then
-       computes the length of its result."""
-    return tree_ir.CallInstruction(
-        tree_ir.LoadGlobalInstruction('len'),
-        [expression])
-
-# Don't compain about the variable names, pylint. It's important that we
-# get them right.
-# pylint: disable=I0011,C0103
-def __set_add(a, b):
-    store_a, load_a = tree_ir.evaluate_and_load(a)
-    store_b, load_b = tree_ir.evaluate_and_load(b)
-    return tree_ir.create_block(
-        store_a,
-        store_b,
-        tree_ir.CreateEdgeInstruction(
-            tree_ir.CreateEdgeInstruction(load_a, a),
-            load_b),
-        load_a)
-
-def __dict_add(a, b, c):
-    store_a, load_a = tree_ir.evaluate_and_load(a)
-    store_b, load_b = tree_ir.evaluate_and_load(b)
-    return tree_ir.create_block(
-        store_a,
-        store_b,
-        tree_ir.CreateEdgeInstruction(
-            tree_ir.CreateEdgeInstruction(load_a, c),
-            load_b),
-        load_a)
-
-def __dict_add_fast(a, b, c):
-    # TODO This might be possible to optimize slightly?
-    store_a, load_a = tree_ir.evaluate_and_load(a)
-    b_val = tree_ir.StoreLocalInstruction(
-        None,
-        tree_ir.ReadValueInstruction(b))
-    store_c, load_c = tree_ir.evaluate_and_load(c)
-    return tree_ir.create_block(
-        store_a,
-        b_val,
-        store_c,
-        tree_ir.CreateDictionaryEdgeInstruction(
-            load_a,
-            b_val.create_load(),
-            load_c),
-        load_a)
-
-def __list_read(a, b):
-    # The statements in this function generate the following code:
-    #
-    # a_tmp = a # To make sure a is evaluated before b.
-    # b_value, = yield [("RV", [b])]
-    # result, = yield [("RD", [a_tmp, b_value])]
-    # if result is None:
-    #     raise Exception("List read out of bounds: %s" % b_value)
-    # result
-
-    store_a, load_a = tree_ir.evaluate_and_load(a)
-    b_val = tree_ir.StoreLocalInstruction(
-        None,
-        tree_ir.ReadValueInstruction(b))
-    result = tree_ir.StoreLocalInstruction(
-        None,
-        tree_ir.ReadDictionaryValueInstruction(
-            load_a.create_load(), b_val.create_load()))
-
-    return tree_ir.create_block(
-        store_a,
-        b_val,
-        result,
-        tree_ir.SelectInstruction(
-            tree_ir.BinaryInstruction(
-                result.create_load(),
-                'is',
-                tree_ir.LiteralInstruction(None)),
-            tree_ir.RaiseInstruction(
-                tree_ir.CallInstruction(
-                    tree_ir.LoadGlobalInstruction('Exception'),
-                    [tree_ir.BinaryInstruction(
-                        tree_ir.LiteralInstruction('List read out of bounds: %s'),
-                        '%',
-                        b_val.create_load())])),
-            tree_ir.EmptyInstruction()),
-        result.create_load())
-
-def __list_append(a, b):
-    # We want to generate code that is more or less equivalent to:
-    #
-    # a_tmp = a
-    # b_tmp = b
-    # a_outgoing, = yield [("RO", [a_tmp])]
-    # _ = yield [("CD", [a_tmp, len(a_outgoing), b_tmp])]
-    # a
-
-    store_a, load_a = tree_ir.evaluate_and_load(a)
-    store_b, load_b = tree_ir.evaluate_and_load(b)
-    return tree_ir.create_block(
-        store_a,
-        store_b,
-        tree_ir.CreateDictionaryEdgeInstruction(
-            load_a,
-            create_get_length(
-                tree_ir.ReadOutgoingEdgesInstruction(
-                    load_a)),
-            load_b),
-        load_a)
-
-def __log(a):
-    # Original definition:
-    #
-    # def log(a, **remainder):
-    #     a_value, = yield [("RV", [a])]
-    #     print("== LOG == " + str(a_value))
-    #     raise PrimitiveFinished(a)
-
-    store_a, load_a = tree_ir.evaluate_and_load(a)
-    return tree_ir.CompoundInstruction(
-        tree_ir.create_block(
-            store_a,
-            tree_ir.PrintInstruction(
-                tree_ir.BinaryInstruction(
-                    tree_ir.LiteralInstruction("== LOG == "),
-                    '+',
-                    tree_ir.CallInstruction(
-                        tree_ir.LoadGlobalInstruction('str'),
-                        [tree_ir.ReadValueInstruction(load_a)])))),
-        load_a)
-
-def __read_nr_out(a):
-    # Original definition:
-    #
-    # def read_nr_out(a, **remainder):
-    #     outgoing, = yield [("RO", [a])]
-    #     result, = yield [("CNV", [len(outgoing)])]
-    #     raise PrimitiveFinished(result)
-
-    return tree_ir.CreateNodeWithValueInstruction(
-        create_get_length(tree_ir.ReadOutgoingEdgesInstruction(a)))
-
-MISC_INTRINSICS = {
-    # Reference equality
-    'element_eq' :
-        lambda a, b:
-        tree_ir.CreateNodeWithValueInstruction(
-            tree_ir.BinaryInstruction(a, '==', b)),
-    'element_neq' :
-        lambda a, b:
-        tree_ir.CreateNodeWithValueInstruction(
-            tree_ir.BinaryInstruction(a, '!=', b)),
-
-    # Strings
-    'string_get' :
-        lambda a, b:
-        tree_ir.CreateNodeWithValueInstruction(
-            tree_ir.LoadIndexInstruction(
-                tree_ir.ReadValueInstruction(a),
-                tree_ir.ReadValueInstruction(b))),
-    'string_len' :
-        lambda a:
-        tree_ir.CreateNodeWithValueInstruction(
-            tree_ir.CallInstruction(
-                tree_ir.LoadGlobalInstruction('len'),
-                [tree_ir.ReadValueInstruction(a)])),
-    'string_join' :
-        lambda a, b:
-        tree_ir.CreateNodeWithValueInstruction(
-            tree_ir.BinaryInstruction(
-                tree_ir.CallInstruction(
-                    tree_ir.LoadGlobalInstruction('str'),
-                    [tree_ir.ReadValueInstruction(a)]),
-                '+',
-                tree_ir.CallInstruction(
-                    tree_ir.LoadGlobalInstruction('str'),
-                    [tree_ir.ReadValueInstruction(b)]))),
-    'string_startswith' :
-        lambda a, b:
-        tree_ir.CreateNodeWithValueInstruction(
-            tree_ir.CallInstruction(
-                tree_ir.LoadMemberInstruction(
-                    tree_ir.ReadValueInstruction(a),
-                    'startswith'),
-                [tree_ir.ReadValueInstruction(b)])),
-
-    # State creation
-    'create_node' : tree_ir.CreateNodeInstruction,
-    'create_edge' :
-        # Lambda is totally necessary here, pylint.
-        # You totally dropped the ball on this one.
-        # pylint: disable=I0011,W0108
-        lambda a, b:
-        tree_ir.CreateEdgeInstruction(a, b),
-    'create_value' :
-        lambda a:
-        tree_ir.CreateNodeWithValueInstruction(
-            tree_ir.ReadValueInstruction(a)),
-
-    # State reads
-    'read_edge_src' :
-        lambda a:
-        tree_ir.LoadIndexInstruction(
-            tree_ir.ReadEdgeInstruction(a),
-            tree_ir.LiteralInstruction(0)),
-    'read_edge_dst' :
-        lambda a:
-        tree_ir.LoadIndexInstruction(
-            tree_ir.ReadEdgeInstruction(a),
-            tree_ir.LiteralInstruction(1)),
-    'is_edge' :
-        lambda a:
-        tree_ir.CreateNodeWithValueInstruction(
-            tree_ir.BinaryInstruction(
-                tree_ir.LoadIndexInstruction(
-                    tree_ir.ReadEdgeInstruction(a),
-                    tree_ir.LiteralInstruction(0)),
-                'is not',
-                tree_ir.LiteralInstruction(None))),
-
-    'read_nr_out' : __read_nr_out,
-
-    # read_root
-    'read_root' :
-        lambda:
-        tree_ir.LoadIndexInstruction(
-            tree_ir.LoadLocalInstruction(jit_runtime.KWARGS_PARAMETER_NAME),
-            tree_ir.LiteralInstruction('root')),
-
-    # read_taskroot
-    'read_taskroot' :
-        lambda:
-        tree_ir.LoadIndexInstruction(
-            tree_ir.LoadLocalInstruction(jit_runtime.KWARGS_PARAMETER_NAME),
-            tree_ir.LiteralInstruction('task_root')),
-
-    # Dictionary operations
-    'dict_create' : tree_ir.CreateNodeInstruction,
-    'dict_len': __read_nr_out,
-    'dict_read' :
-        lambda a, b:
-        tree_ir.ReadDictionaryValueInstruction(
-            a, tree_ir.ReadValueInstruction(b)),
-
-    'dict_read_edge' :
-        lambda a, b:
-        tree_ir.ReadDictionaryEdgeInstruction(
-            a, tree_ir.ReadValueInstruction(b)),
-
-    'dict_add' : __dict_add,
-    'dict_add_fast' : __dict_add_fast,
-    'dict_len' : __read_nr_out,
-
-    # Set operations
-    'set_create' : tree_ir.CreateNodeInstruction,
-    'set_add' : __set_add,
-    'set_len' : __read_nr_out,
-
-    # List operations
-    'list_create' : tree_ir.CreateNodeInstruction,
-    'list_len' : __read_nr_out,
-    'list_read' : __list_read,
-    'list_append' : __list_append,
-
-    # log
-    'log' : __log
-}
-
-def __read_nr_out_cfg(original_def, a):
-    # Original definition:
-    #
-    # def read_nr_out(a, **remainder):
-    #     outgoing, = yield [("RO", [a])]
-    #     result, = yield [("CNV", [len(outgoing)])]
-    #     raise PrimitiveFinished(result)
-
-    original_def.redefine(
-        cfg_ir.CreateNode(
-            original_def.insert_before(
-                cfg_ir.create_pure_simple_call(
-                    'len',
-                    original_def.insert_before(
-                        cfg_ir.create_read_outgoing_edges(a))))))
-
-def __dict_in_cfg(original_def, a, b):
-    # Original definition:
-    #
-    # def dict_in(a, b, **remainder):
-    #     b_value, = yield [("RV", [b])]
-    #     value, = yield [("RD", [a, b_value])]
-    #     is_in = value is not None
-    #     result, = yield [("CNV", [is_in])]
-    #     raise PrimitiveFinished(result)
-
-    original_def.redefine(
-        cfg_ir.CreateNode(
-            original_def.insert_before(
-                cfg_ir.Binary(
-                    original_def.insert_before(
-                        cfg_ir.create_read_dict_value(
-                            a, original_def.insert_before(cfg_ir.Read(b)))),
-                    'is not',
-                    original_def.insert_before(cfg_ir.Literal(None))))))
-
-def __dict_in_node_cfg(original_def, a, b):
-    # Original definition:
-    #
-    # def dict_in_node(a, b, **remainder):
-    #     value, = yield [("RDN", [a, b])]
-    #     result, = yield [("CNV", [value is not None])]
-    #     raise PrimitiveFinished(result)
-
-    original_def.redefine(
-        cfg_ir.CreateNode(
-            original_def.insert_before(
-                cfg_ir.Binary(
-                    original_def.insert_before(cfg_ir.create_read_dict_node(a, b)),
-                    'is not',
-                    original_def.insert_before(cfg_ir.Literal(None))))))
-
-def __dict_read_cfg(original_def, a, b):
-    # Original definition:
-    #
-    # def dict_read(a, b, **remainder):
-    #     b_value, = yield [("RV", [b])]
-    #     result, = yield [("RD", [a, b_value])]
-    #     raise PrimitiveFinished(result)
-
-    original_def.redefine(
-        cfg_ir.create_read_dict_value(
-            a,
-            original_def.insert_before(cfg_ir.Read(b))))
-
-MISC_CFG_INTRINSICS = {
-    # Reference equality
-    'element_eq' :
-        lambda original_def, a, b:
-        original_def.redefine(
-            cfg_ir.CreateNode(
-                original_def.insert_before(
-                    cfg_ir.Binary(a, '==', b)))),
-    'element_neq' :
-        lambda original_def, a, b:
-        original_def.redefine(
-            cfg_ir.CreateNode(
-                original_def.insert_before(
-                    cfg_ir.Binary(a, '!=', b)))),
-
-
-    # String operations
-    'string_get' :
-        lambda original_def, a, b:
-        original_def.redefine(
-            cfg_ir.CreateNode(
-                original_def.insert_before(
-                    cfg_ir.create_index(
-                        original_def.insert_before(cfg_ir.Read(a)),
-                        original_def.insert_before(cfg_ir.Read(b)))))),
-    'string_len' :
-        lambda original_def, a:
-        original_def.redefine(
-            cfg_ir.CreateNode(
-                original_def.insert_before(
-                    cfg_ir.create_pure_simple_call(
-                        'len',
-                        original_def.insert_before(cfg_ir.Read(a)))))),
-    'string_join' :
-        lambda original_def, a, b:
-        original_def.redefine(
-            cfg_ir.CreateNode(
-                original_def.insert_before(
-                    cfg_ir.Binary(
-                        original_def.insert_before(
-                            cfg_ir.create_pure_simple_call(
-                                'str',
-                                original_def.insert_before(cfg_ir.Read(a)))),
-                        '+',
-                        original_def.insert_before(
-                            cfg_ir.create_pure_simple_call(
-                                'str',
-                                original_def.insert_before(cfg_ir.Read(b)))))))),
-    'string_startswith' :
-        lambda original_def, a, b:
-        original_def.redefine(
-            cfg_ir.CreateNode(
-                original_def.insert_before(
-                    cfg_ir.DirectFunctionCall(
-                        'startswith',
-                        [('self', original_def.insert_before(cfg_ir.Read(a))),
-                         ('substring', original_def.insert_before(cfg_ir.Read(b)))],
-                        calling_convention=cfg_ir.SELF_POSITIONAL_CALLING_CONVENTION,
-                        has_value=True, has_side_effects=False)))),
-
-    # State creation
-    'create_node' :
-        lambda original_def:
-        original_def.redefine(
-            cfg_ir.CreateNode(original_def.insert_before(cfg_ir.Literal(None)))),
-    'create_value' :
-        lambda original_def, a:
-        original_def.redefine(
-            cfg_ir.CreateNode(original_def.insert_before(cfg_ir.Read(a)))),
-
-    # State reads
-    'read_nr_out' : __read_nr_out_cfg,
-
-    # Dictionary operations
-    'dict_len' : __read_nr_out_cfg,
-    'dict_read' : __dict_read_cfg,
-    'dict_in' : __dict_in_cfg,
-    'dict_in_node' : __dict_in_node_cfg,
-
-    'set_in' : __dict_in_cfg,
-    'set_len' : __read_nr_out_cfg,
-
-    # List operations
-    'list_len' : __read_nr_out_cfg,
-
-    'list_create' :
-        lambda original_def:
-        original_def.redefine(
-            cfg_ir.CreateNode(original_def.insert_before(cfg_ir.Literal(None)))),
-    'set_create' :
-        lambda original_def:
-        original_def.redefine(
-            cfg_ir.CreateNode(original_def.insert_before(cfg_ir.Literal(None)))),
-    'dict_create' :
-        lambda original_def:
-        original_def.redefine(
-            cfg_ir.CreateNode(original_def.insert_before(cfg_ir.Literal(None)))),
-}
-
-def register_time_intrinsic(target_jit):
-    """Registers the time() intrinsic with the given JIT."""
-    import_name = target_jit.import_value(time.time, 'time')
-    target_jit.register_intrinsic(
-        'time',
-        lambda: tree_ir.CreateNodeWithValueInstruction(
-            tree_ir.CallInstruction(
-                tree_ir.LoadGlobalInstruction(import_name),
-                [])))
-
-def register_intrinsics(target_jit):
-    """Registers all intrinsics in the module with the given JIT."""
-    for (key, value) in list(BINARY_INTRINSICS.items()):
-        target_jit.register_binary_intrinsic(key, value)
-    for (key, value) in list(UNARY_INTRINSICS.items()):
-        target_jit.register_unary_intrinsic(key, value)
-    for (key, value) in list(CAST_INTRINSICS.items()):
-        target_jit.register_cast_intrinsic(key, value)
-    for (key, value) in list(MISC_INTRINSICS.items()):
-        target_jit.register_intrinsic(key, value)
-    for (key, value) in list(MISC_CFG_INTRINSICS.items()):
-        target_jit.register_cfg_intrinsic(key, value)
-
-    register_time_intrinsic(target_jit)

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1043
kernel/modelverse_jit/jit.py


+ 0 - 16
kernel/modelverse_jit/jit_primitives.py

@@ -1,16 +0,0 @@
-"""Primitive functions that interface with the Modelverse JIT."""
-
-import modelverse_kernel.primitives as primitive_functions
-
-# pylint: disable=I0011,C0103
-
-def get_jit_enabled(**kwargs):
-    """Checks if the JIT is enabled."""
-    result, = yield [("CNV", [kwargs['mvk'].jit.jit_enabled])]
-    raise primitive_functions.PrimitiveFinished(result)
-
-def set_jit_enabled(a, **kwargs):
-    """Enables or disables the JIT."""
-    val, result = yield [("RV", [a]), ("CN", [])]
-    kwargs['mvk'].jit.set_jit_enabled(val)
-    raise primitive_functions.PrimitiveFinished(result)

+ 0 - 191
kernel/modelverse_jit/runtime.py

@@ -1,191 +0,0 @@
-import modelverse_kernel.primitives as primitive_functions
-
-class JitCompilationFailedException(Exception):
-    """A type of exception that is raised when the jit fails to compile a function."""
-    pass
-
-MUTABLE_FUNCTION_KEY = "mutable"
-"""A dictionary key for functions that are mutable."""
-
-FUNCTION_BODY_KEY = "body"
-"""A dictionary key for function bodies."""
-
-KWARGS_PARAMETER_NAME = "kwargs"
-"""The name of the kwargs parameter in jitted functions."""
-
-CALL_FUNCTION_NAME = "__call_function"
-"""The name of the '__call_function' function, in the jitted function scope."""
-
-GET_INPUT_FUNCTION_NAME = "__get_input"
-"""The name of the '__get_input' function, in the jitted function scope."""
-
-JIT_THUNK_CONSTANT_FUNCTION_NAME = "__jit_thunk_constant_function"
-"""The name of the jit_thunk_constant_function function in the JIT's global context."""
-
-JIT_THUNK_GLOBAL_FUNCTION_NAME = "__jit_thunk_global"
-"""The name of the jit_thunk_global function in the JIT's global context."""
-
-JIT_REJIT_FUNCTION_NAME = "__jit_rejit"
-"""The name of the rejit function in the JIT's global context."""
-
-JIT_COMPILE_FUNCTION_BODY_FAST_FUNCTION_NAME = "__jit_compile_function_body_fast"
-"""The name of the compile_function_body_fast function in the JIT's global context."""
-
-UNREACHABLE_FUNCTION_NAME = "__unreachable"
-"""The name of the unreachable function in the JIT's global context."""
-
-LOCALS_NODE_NAME = "jit_locals"
-"""The name of the node that is connected to all JIT locals in a given function call."""
-
-LOCALS_EDGE_NAME = "jit_locals_edge"
-"""The name of the edge that connects the LOCALS_NODE_NAME node to a user root."""
-
-GLOBAL_NOT_FOUND_MESSAGE_FORMAT = "Not found as global: %s"
-"""The format of the 'not found as global' message. Takes a single argument."""
-
-BYTECODE_INTERPRETER_ORIGIN_NAME = "bytecode-interpreter"
-"""The origin name for functions that were produced by the bytecode interpreter."""
-
-BASELINE_JIT_ORIGIN_NAME = "baseline-jit"
-"""The origin name for functions that were produced by the baseline JIT."""
-
-FAST_JIT_ORIGIN_NAME = "fast-jit"
-"""The origin name for functions that were produced by the fast JIT."""
-
-def format_stack_frame(function_name, debug_info, origin='unknown'):
-    """Formats a stack frame, which consists of a function name, debug
-       information and an origin."""
-    if function_name is None:
-        function_name = 'unknown function'
-    if debug_info is None:
-        debug_info = '[unknown location] '
-
-    return '%sin %s (%s)' % (debug_info, function_name, origin)
-
-def format_trace_message(debug_info, function_name, origin='unknown'):
-    """Creates a formatted trace message."""
-    return 'TRACE: %s' % format_stack_frame(function_name, debug_info, origin)
-
-def call_function(function_id, named_arguments, **kwargs):
-    """Runs the function with the given id, passing it the specified argument dictionary."""
-    task_root = kwargs['task_root']
-    kernel = kwargs['mvk']
-    body_id, is_mutable = yield [
-        ("RD", [function_id, FUNCTION_BODY_KEY]),
-        ("RD", [function_id, MUTABLE_FUNCTION_KEY])]
-
-    # Try to jit the function here. We might be able to avoid building the stack
-    # frame.
-    def handle_jit_failed(_):
-        """Interprets the function."""
-        interpreter_args = {'body_id' : body_id, 'named_arguments' : named_arguments}
-        interpreter_args.update(kwargs)
-        yield [("TAIL_CALL_KWARGS", [interpret_function_body, interpreter_args])]
-
-    if is_mutable is not None:
-        kernel.jit.mark_no_jit(body_id)
-        yield [("TAIL_CALL_ARGS", [handle_jit_failed, ()])]
-    else:
-        kernel.jit.mark_entry_point(body_id)
-
-    yield [("TRY", [])]
-    yield [("CATCH", [JitCompilationFailedException, handle_jit_failed])]
-    # Try to compile.
-    compiled_func, = yield [("CALL_ARGS", [kernel.jit_compile, (task_root, body_id)])]
-    yield [("END_TRY", [])]
-    # Add the keyword arguments to the argument dictionary.
-    named_arguments.update(kwargs)
-    # Run the function.
-    yield [("TAIL_CALL_KWARGS", [compiled_func, named_arguments])]
-
-def interpret_function(function_id, named_arguments, **kwargs):
-    """Makes the interpreter run the function with the given id for the specified
-       argument dictionary."""
-    body_id, = yield [("RD", [function_id, FUNCTION_BODY_KEY])]
-    args = {'body_id' : body_id, named_arguments : named_arguments}
-    args.update(kwargs)
-    yield [("TAIL_CALL_KWARGS", [interpret_function_body, args])]
-
-def interpret_function_body(body_id, named_arguments, **kwargs):
-    """Makes the interpreter run the function body with the given id for the specified
-       argument dictionary."""
-    task_root = kwargs['task_root']
-    kernel = kwargs['mvk']
-    user_frame, = yield [("RD", [task_root, "frame"])]
-    inst, = yield [("RD", [user_frame, "IP"])]
-    kernel.jit.mark_entry_point(body_id)
-
-    # Create a new stack frame.
-    frame_link, new_phase, new_frame, new_evalstack, new_symbols, \
-        new_returnvalue, intrinsic_return = \
-                    yield [("RDE", [task_root, "frame"]),
-                           ("CNV", ["init"]),
-                           ("CN", []),
-                           ("CN", []),
-                           ("CN", []),
-                           ("CN", []),
-                           ("CN", [])
-                          ]
-
-    _, _, _, _, _, _, _, _, _, _ = \
-                    yield [("CD", [task_root, "frame", new_frame]),
-                           ("CD", [new_frame, "evalstack", new_evalstack]),
-                           ("CD", [new_frame, "symbols", new_symbols]),
-                           ("CD", [new_frame, "returnvalue", new_returnvalue]),
-                           ("CD", [new_frame, "caller", inst]),
-                           ("CD", [new_frame, "phase", new_phase]),
-                           ("CD", [new_frame, "IP", body_id]),
-                           ("CD", [new_frame, "prev", user_frame]),
-                           ("CD", [
-                               new_frame,
-                               primitive_functions.EXCEPTION_RETURN_KEY,
-                               intrinsic_return]),
-                           ("DE", [frame_link])
-                          ]
-
-    # Put the parameters in the new stack frame's symbol table.
-    (parameter_vars, parameter_names, _), = yield [
-        ("CALL_ARGS", [kernel.jit.jit_signature, (body_id,)])]
-    parameter_dict = dict(list(zip(parameter_names, parameter_vars)))
-
-    for (key, value) in list(named_arguments.items()):
-        param_var = parameter_dict[key]
-        variable, = yield [("CN", [])]
-        yield [("CD", [variable, "value", value])]
-        symbol_edge, = yield [("CE", [new_symbols, variable])]
-        yield [("CE", [symbol_edge, param_var])]
-
-    taskname = kwargs['taskname']
-    def exception_handler(ex):
-        # print('Returning from interpreted function. Result: %s' % ex.result)
-        raise primitive_functions.PrimitiveFinished(ex.result)
-
-    # Create an exception handler to catch and translate InterpretedFunctionFinished.
-    yield [("TRY", [])]
-    yield [("CATCH", [primitive_functions.InterpretedFunctionFinished, exception_handler])]
-    while 1:
-        result, = yield [("CALL_ARGS", [kernel.execute_rule, (taskname,)])]
-        # An instruction has completed. Forward it.
-        yield result
-
-class UnreachableCodeException(Exception):
-    """The type of exception that is thrown when supposedly unreachable code is executed."""
-    pass
-
-def unreachable():
-    """Marks unreachable code."""
-    raise UnreachableCodeException('An unreachable statement was reached.')
-
-def get_input(**parameters):
-    """Retrieves input."""
-    mvk = parameters["mvk"]
-    task_root = parameters["task_root"]
-    while 1:
-        yield [("CALL_ARGS", [mvk.input_init, (task_root,)])]
-        # Finished
-        if mvk.input_value is not None:
-            # Got some input, so we can access it
-            raise primitive_functions.PrimitiveFinished(mvk.input_value)
-        else:
-            # No input, so yield None but don't stop
-            yield None

+ 0 - 52
kernel/modelverse_jit/source_map.py

@@ -1,52 +0,0 @@
-"""Defines source maps: dictionaries that map lines in generated source to debug information."""
-
-class SourceMap(object):
-    """A source map, which converts generated source lines to debug information."""
-    def __init__(self):
-        self.lines = {}
-
-    def map_line(self, line_number, debug_info):
-        """Assigns the given debug information to the given line."""
-        self.lines[line_number] = debug_info
-
-    def get_debug_info(self, line_number):
-        """Gets the debug information for the given line number, or None if no debug info was
-           found."""
-        if line_number in self.lines:
-            return self.lines[line_number]
-        else:
-            return None
-
-    def __str__(self):
-        return '\n'.join(
-            ['%d: %s' % pair
-             for pair in sorted(list(self.lines.items()), key=lambda key: key[0])])
-
-class SourceMapBuilder(object):
-    """A type of object that makes it easy to build source maps for hierarchical instructions."""
-    def __init__(self, initial_line_number=0):
-        self.source_map = SourceMap()
-        self.debug_info_stack = []
-        self.line_number = initial_line_number - 1
-
-    def push_debug_info(self, debug_info):
-        """Informs the source map that subsequent lines of code will have the given debug
-           information associated with them."""
-        self.debug_info_stack.append(debug_info)
-
-    def pop_debug_info(self):
-        """Informs the source map that the debug information that was pushed last should
-           be discarded in favor of the debug information that was pushed onto the stack
-           just prior to it."""
-        return self.debug_info_stack.pop()
-
-    def append_line(self):
-        """Has the source map builder increment its line number counter, and assigns the debug
-           information that is at the top of the debug information stack to that line."""
-        self.line_number += 1
-        if len(self.debug_info_stack) > 0:
-            self.source_map.map_line(self.line_number, self.debug_info_stack[-1])
-
-    def __str__(self):
-        return str(self.source_map)
-

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1954
kernel/modelverse_jit/tree_ir.py


+ 208 - 115
kernel/modelverse_kernel/compiled.py

@@ -1,14 +1,12 @@
-from modelverse_kernel.primitives import PrimitiveFinished
-import modelverse_jit.runtime as jit_runtime
 import time
 
 def get_superclasses(a, b, **remainder):
-    model, name = a, b
-    model_dict, tm_dict, name_value = yield [("RD", [a, "model"]), 
-                                             ("RD", [a, "type_mapping"]),
-                                             ("RV", [b])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    model_dict, tm_dict = yield [("RD", [a['id'], "model"]), 
+                                 ("RD", [a['id'], "type_mapping"])]
 
-    worklist = set([name_value])
+    worklist = set([b['value']])
     found = set([])
 
     cache_value = {}
@@ -21,41 +19,49 @@ def get_superclasses(a, b, **remainder):
         found.add(name)
 
         # Iterate over all outgoing links
+        if elem is None:
+            print("ERROR: " + str(locals()))
         outgoing, = yield [("RO", [elem])]
         outgoing = set(outgoing)
         while (outgoing):
             link = outgoing.pop()
 
             # If the link is typed by "Inheritance", we add its destination
-            link_name_node, = yield [("CALL_ARGS", [reverseKeyLookup, [model_dict, link]])]
-            link_name, = yield [("RV", [link_name_node])]
-            t_edge, = yield [("RD", [tm_dict, link_name])]
+            link_name_node, = yield [("CALL_ARGS", [reverseKeyLookup, [{'id': model_dict}, {'id': link}]])]
+            if "value" not in link_name_node:
+                link_name_node['value'], = yield [("RV", [link_name_node['id']])]
+
+            t_edge, = yield [("RD", [tm_dict, link_name_node['value']])]
             t_edge, = yield [("RV", [t_edge])]
             if t_edge == "Inheritance":
                 edge, = yield [("RE", [link])]
                 src, dst = edge
                 # Look up dst's name and add it
                 if dst not in cache_value:
-                    dst_name, = yield [("CALL_ARGS", [reverseKeyLookup, [model_dict, dst]])]
-                    dst_name_value, = yield [("RV", [dst_name])]
-                    cache_value[dst] = dst_name_value
+                    dst_name, = yield [("CALL_ARGS", [reverseKeyLookup, [{'id': model_dict}, {'id': dst}]])]
+                    if 'value' not in dst_name:
+                        dst_name['value'], = yield [("RV", [dst_name['id']])]
+                    cache_value[dst] = dst_name['value']
                 dst_name_value = cache_value[dst]
                 worklist.add(dst_name_value)
 
     result, = yield [("CN", [])]
     yield [("CD", [result, i, result]) for i in found]
 
-    raise PrimitiveFinished(result)
+    yield [("RETURN", [{'id': result}])]
 
 def reverseKeyLookupMulti(a, b, **remainder):
-    edges, b_val, result = yield [("RO", [a]), ("RV", [b]), ("CN", [])]
+    if "value" not in b:
+        b['value'], = yield [("RV", [b['id']])]
+
+    edges, result = yield [("RO", [a['id']]), ("CN", [])]
     expanded_edges = yield [("RE", [i]) for i in edges]
     values = yield [("RV", [i[1]]) for i in expanded_edges]
 
     # Keep results in a local Python set, as we want to bundle as many requests as possible
     todo = set()
     for i, edge in enumerate(values):
-        if b_val == edge:
+        if b['value'] == edge:
             todo.add(i)
 
     outgoings = yield [("RO", [edges[i]]) for i in todo]
@@ -63,13 +69,14 @@ def reverseKeyLookupMulti(a, b, **remainder):
     edges = yield [("CE", [result, result]) for value in values]
     yield [("CE", [edge, value[1]]) for edge, value in zip(edges, values)]
 
-    raise PrimitiveFinished(result)
+    yield [("RETURN", [{'id': result}])]
 
 def reverseKeyLookup(a, b, **remainder):
-    if a is None or b is None:
-        result, = yield [("CNV", [""])]
-        raise PrimitiveFinished(result)
-    edges_out, edges_in = yield [("RO", [a]), ("RI", [b])]
+    edges_out, edges_in = yield [("RO", [a['id']]), ("RI", [b['id']])]
+
+    if edges_out is None or edges_in is None:
+        yield [("RETURN", [{'value': ""}])]
+
     options = set(edges_out) & set(edges_in)
     if options:
         # Select one option randomly
@@ -78,201 +85,287 @@ def reverseKeyLookup(a, b, **remainder):
         # Select one option randomly
         out_edge = out_edges.pop()
         e, = yield [("RE", [out_edge])]
-        result = e[1]
+        yield [("RETURN", [{'id': e[1]}])]
     else:
-        result, = yield [("CNV", [""])]
-    raise PrimitiveFinished(result)
+        yield [("RETURN", [{'value': ""}])]
 
 def instantiated_name(a, b, **remainder):
-    name_value, = yield [("RV", [b])]
-    if name_value == "":
-        b, = yield [("CNV", ["__" + str(a)])]
-    raise PrimitiveFinished(b)
+    if "id" not in a:
+        a['id'], = yield [("CNV", [a['value']])]
+    if "value" not in b:
+        b['value'], = yield [("RV", [b["id"]])]
+
+    if b['value'] == "":
+        yield [("RETURN", [{'value': "__" + str(a['id'])}])]
+    else:
+        yield [("RETURN", [b])]
 
 def set_merge(a, b, **remainder):
-    keys, =         yield [("RDK", [b])]
-    edges =         yield [("CE", [a, a]) for key in keys]
+    keys, =         yield [("RDK", [b['id']])]
+    edges =         yield [("CE", [a['id'], a['id']]) for key in keys]
     _ =             yield [("CE", [edge, key]) for edge, key in zip(edges, keys)]
-    raise PrimitiveFinished(a)
+    yield [("RETURN", [a])]
 
 def has_value(a, **remainder):
-    v, = yield [("RV", [a])]
-    if v is None:
-        result, = yield [("CNV", [False])]
+    if "value" not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if a['value'] is None:
+        yield [("RETURN", [{'value': False}])]
     else:
-        result, = yield [("CNV", [True])]
-    raise PrimitiveFinished(result)
+        yield [("RETURN", [{'value': True}])]
 
 def make_reverse_dictionary(a, **remainder):
     reverse, = yield [("CN", [])]
-    key_nodes, = yield [("RDK", [a])]
-    values = yield [("RDN", [a, i]) for i in key_nodes]
+    key_nodes, = yield [("RDK", [a['id']])]
+    values = yield [("RDN", [a['id'], i]) for i in key_nodes]
     yield [("CD", [reverse, str(v), k]) for k, v in zip(key_nodes, values)]
-    raise PrimitiveFinished(reverse)
+    yield [("RETURN", [{'id': reverse}])]
 
 def dict_eq(a, b, **remainder):
-    key_nodes, = yield [("RDK", [a])]
+    key_nodes, = yield [("RDK", [a['id']])]
     key_values = yield [("RV", [i]) for i in key_nodes]
-    values = yield [("RD", [a, i]) for i in key_values]
+    values = yield [("RD", [a['id'], i]) for i in key_values]
     values = yield [("RV", [i]) for i in values]
     a_dict = dict(list(zip(key_values, values)))
 
-    key_nodes, = yield [("RDK", [b])]
+    key_nodes, = yield [("RDK", [b['id']])]
     key_values = yield [("RV", [i]) for i in key_nodes]
-    values = yield [("RD", [b, i]) for i in key_values]
+    values = yield [("RD", [b['id'], i]) for i in key_values]
     values = yield [("RV", [i]) for i in values]
     b_dict = dict(list(zip(key_values, values)))
 
-    result, = yield [("CNV", [a_dict == b_dict])]
-    raise PrimitiveFinished(result)
+    yield [("RETURN", [{'value': a_dict == b_dict}])]
 
 def string_substr(a, b, c, **remainder):
-    a_val, b_val, c_val = yield [("RV", [a]),
-                                 ("RV", [b]),
-                                 ("RV", [c])]
+    if "value" not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if "value" not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    if "value" not in c:
+        c['value'], = yield [("RV", [c['id']])]
+
     try:
-        new_value = a_val[b_val:c_val]
+        new_value = a['value'][b['value']:c['value']]
     except:
         new_value = ""
     
-    result, = yield [("CNV", [new_value])]
-    raise PrimitiveFinished(result)
+    yield [("RETURN", [{'value': new_value}])]
 
 def integer_gt(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value > b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] > b['value']}])]
 
 def integer_neg(a, **remainder):
-    a_value, =          yield [("RV", [a])]
-    result, = yield [("CNV", [-a_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    yield [("RETURN", [{'value': -a['value']}])]
 
 def float_gt(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value > b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] > b['value']}])]
 
 def float_neg(a, **remainder):
-    a_value, =          yield [("RV", [a])]
-    result, = yield [("CNV", [-a_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    yield [("RETURN", [{'value': -a['value']}])]
 
 def value_neq(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value != b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] != b['value']}])]
 
 def element_neq(a, b, **remainder):
-    result, = yield [("CNV", [a != b])]
-    raise PrimitiveFinished(result)
+    if 'id' not in a or 'id' not in b:
+        yield [("RETURN", [{'value': False}])]
+    else:
+        yield [("RETURN", [{'value': a['id'] != b['id']}])]
 
 def list_append(a, b, **remainder):
-    a_outgoing, = yield [("RO", [a])]
-    _ = yield [("CD", [a, len(a_outgoing), b])]
-    raise PrimitiveFinished(a)
+    if "id" not in b:
+        b['id'], = yield [("CNV", [b['value']])]
+    a_outgoing, = yield [("RO", [a['id']])]
+    _ = yield [("CD", [a['id'], len(a_outgoing), b['id']])]
+    yield [("RETURN", [a])]
 
 def list_read(a, b, **remainder):
-    b_value, = yield [("RV", [b])]
-    result, = yield [("RD", [a, b_value])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    result, = yield [("RD", [a['id'], b['value']])]
     if result is None:
-        raise Exception("List read out of bounds: %s" % b_value)
-    raise PrimitiveFinished(result)
+        raise Exception("List read out of bounds: %s" % b['value'])
+    yield [("RETURN", [{'id': result}])]
 
 def list_len(a, **remainder):
-    outgoings, = yield [("RO", [a])]
+    outgoings, = yield [("RO", [a['id']])]
     result, = yield [("CNV", [len(outgoings)])]
-    raise PrimitiveFinished(result)
+    yield [("RETURN", [{'id': result}])]
 
 def dict_add(a, b, c, **remainder):
-    new_edge, = yield [("CE", [a, c])]
-    yield [("CE", [new_edge, b])]
-    raise PrimitiveFinished(a)
+    if 'id' not in b:
+        b['id'], = yield [("CNV", [b['value']])]
+    if 'id' not in c:
+        c['id'], = yield [("CNV", [c['value']])]
+    new_edge, = yield [("CE", [a['id'], c['id']])]
+    yield [("CE", [new_edge, b['id']])]
+    yield [("RETURN", [a])]
 
 def dict_len(a, **remainder):
-    outgoings, = yield [("RO", [a])]
-    result, = yield [("CNV", [len(outgoings)])]
-    raise PrimitiveFinished(result)
+    outgoings, = yield [("RO", [a['id']])]
+    yield [("RETURN", [{'value': len(outgoings)}])]
 
 def set_add(a, b, **remainder):
-    v, =        yield [("RV", [b])]
-    is_in, =    yield [("RD", [a, v])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    is_in, =    yield [("RD", [a['id'], b['value']])]
     if not is_in:
-        _, =    yield [("CD", [a, v, a])]
-    raise PrimitiveFinished(a)
+        _, =    yield [("CD", [a['id'], b['value'], a['id']])]
+    yield [("RETURN", [a])]
 
 def set_add_node(a, b, **remainder):
-    is_in, =    yield [("RDN", [a, b])]
+    if 'id' not in b:
+        b['id'], = yield [("CNV", [b['value']])]
+    is_in, =    yield [("RDN", [a['id'], b['id']])]
     if not is_in:
-        edge, = yield [("CE", [a, a])]
-        _, =    yield [("CE", [edge, b])]
-    raise PrimitiveFinished(a)
+        edge, = yield [("CE", [a['id'], a['id']])]
+        _, =    yield [("CE", [edge, b['id']])]
+    yield [("RETURN", [a])]
 
 def set_pop(a, **remainder):
-    outgoing, = yield [("RO", [a])]
+    outgoing, = yield [("RO", [a['id']])]
     if outgoing:
         outgoing = outgoing[0]
         new_outgoing, = yield [("RO", [outgoing])]
         new_outgoing = new_outgoing[0]
         edge, _ = yield [("RE", [new_outgoing]), ("DE", [outgoing])]
-        raise PrimitiveFinished(edge[1])
+        yield [("RETURN", [{'id': edge[1]}])]
     else:
         raise Exception("POP from empty set")
-        print("Pop from empty set!")
-        raise PrimitiveFinished(remainder["root"])
+        yield [("RETURN", [{'id': remainder["root"]}])]
 
 def set_create(**remainder):
     result, = yield [("CN", [])]
-    raise PrimitiveFinished(result)
+    yield [("RETURN", [{'id': result}])]
 
 def list_create(**remainder):
     result, = yield [("CN", [])]
-    raise PrimitiveFinished(result)
+    yield [("RETURN", [{'id': result}])]
 
 def dict_create(**remainder):
     result, = yield [("CN", [])]
-    raise PrimitiveFinished(result)
+    yield [("RETURN", [{'id': result}])]
 
 def create_tuple(a, b, **remainder):
+    if "id" not in a:
+        a['id'], = yield [("CNV", [a['value']])]
+    if "id" not in b:
+        b['id'], = yield [("CNV", [b['value']])]
+
     result, = yield [("CN", [])]
-    _, _ =    yield [("CD", [result, 0, a]),
-                     ("CD", [result, 1, b]),
+    _, _ =    yield [("CD", [result, 0, a['id']]),
+                     ("CD", [result, 1, b['id']]),
                     ]
-    raise PrimitiveFinished(result)
+    yield [("RETURN", [{'id': result}])]
 
 def set_overlap(a, b, **remainder):
-    a_keys, b_keys, res = yield [("RDK", [a]), ("RDK", [b]), ("CN", [])]
+    a_keys, b_keys, res = yield [("RDK", [a['id']]), ("RDK", [b['id']]), ("CN", [])]
     a_values = yield [("RV", [i]) for i in a_keys]
     b_values = yield [("RV", [i]) for i in b_keys]
 
     result = set(a_values) & set(b_values)
     yield [("CD", [res, value, res]) for value in result]
 
-    raise PrimitiveFinished(res)
+    yield [("RETURN", [{'id': res}])]
 
 def list_pop_final(a, **remainder):
-    lst, = yield [("RO", [a])]
+    lst, = yield [("RO", [a['id']])]
     length = len(lst)
-    result, result_edge = yield [("RD", [a, length - 1]),
-                                 ("RDE", [a, length -1])]
+    result, result_edge = yield [("RD", [a['id'], length - 1]),
+                                 ("RDE", [a['id'], length -1])]
     _, = yield [("DE", [result_edge])]
-    raise PrimitiveFinished(result)
+    yield [("RETURN", [{'id': result}])]
 
 def instantiate_node(a, b, c, **remainder):
-    node, dict_entry, typing, name = \
+    if "value" not in c:
+        c['value'], = yield [("RV", [c['id']])]
+    if "id" not in b:
+        b['id'], = yield [("CNV", [b['value']])]
+
+    node, dict_entry, typing = \
         yield [("CN", []),
-               ("RD", [a, "model"]),
-               ("RD", [a, "type_mapping"]),
-               ("RV", [c]),
+               ("RD", [a['id'], "model"]),
+               ("RD", [a['id'], "type_mapping"]),
               ]
 
-    if name == "":
+    if c['value'] == "":
         name = "__" + str(node)
-        name_node, = yield [("CNV", [name])]
+        name_node = {'value': name}
     else:
+        name = c['value']
         name_node = c
 
     yield [("CD", [dict_entry, name, node])]
-    yield [("CD", [typing, name, b])]
+    yield [("CD", [typing, name, b['id']])]
+
+    yield [("RETURN", [name_node])]
+
+def list_insert(a, b, c, **remainder):
+    if "id" not in b:
+        b["id"], = yield [("CNV", [b['value']])]
+    if "value" not in c:
+        c['value'], = yield [("RV", [c['id']])]
+
+    a_outgoing, = yield [("RO", [a['id']])]
+    links = yield [("RD", [a['id'], i]) for i in range(c['value'], len(a_outgoing))] + \
+                  [("RDE", [a['id'], i]) for i in range(c['value'], len(a_outgoing))]
+
+    values = links[:len(links) // 2]
+    edges = links[len(links) // 2:] 
+
+    yield [("CD", [a['id'], c['value'], b['id']])] + \
+          [("CD", [a['id'], c['value'] + 1 + index, value]) for index, value in enumerate(values)] + \
+          [("DE", [i]) for i in edges]
+    yield [("RETURN", [a])]
+
+def list_delete(a, b, **remainder):
+    if "value" not in b:
+        b['value'], = yield [("RV", [b['id']])]
+
+    a_outgoing,  = yield [("RO", [a['id']])]
+    links = yield [("RD", [a['id'], i]) for i in range(b['value'], len(a_outgoing))] + \
+                  [("RDE", [a['id'], i]) for i in range(b['value'], len(a_outgoing))]
+
+    values = links[:len(links) // 2]
+    edges = links[len(links) // 2:]
+
+    yield [("CD", [a['id'], b['value'] + index, value]) for index, value in enumerate(values[1:])] + \
+          [("DE", [i]) for i in edges]
+    yield [("RETURN", [a])]
+
+def set_len(a, **remainder):
+    if "id" not in a:
+        yield [("RETURN", [{'value': 0}])]
+    else:
+        outgoing, = yield [("RO", [a['id']])]
+        yield [("RETURN", [{'value': len(outgoing)}])]
+
+def set_in(a, b, **remainder):
+    if "value" not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    value, = yield [("RD", [a['id'], b['value']])]
+    yield [("RETURN", [{'value': value is not None}])]
+
+def set_in_node(a, b, **remainder):
+    if "id" not in b:
+        # Not even allocated the node, so it is certain not to be in the dictionary
+        yield [("RETURN", [{'value': False}])]
+    value, = yield [("RDN", [a['id'], b['id']])]
+    yield [("RETURN", [{'value': value is not None}])]
 
-    raise PrimitiveFinished(name_node)

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1261
kernel/modelverse_kernel/generated.py


+ 190 - 0
kernel/modelverse_kernel/jit.py

@@ -0,0 +1,190 @@
+import math
+import keyword
+from collections import defaultdict
+import modelverse_kernel.primitives as primitive_functions
+
+class ModelverseJit(object):
+    """A high-level interface to the modelverse JIT compiler."""
+    def __init__(self):
+        self.todo_entry_points = set()
+        self.jitted_parameters = {}
+        self.jit_globals = {}
+        # jitted_entry_points maps body ids to values in jit_globals.
+        self.jitted_entry_points = {}
+        # global_functions maps global value names to body ids.
+        self.global_functions = {}
+        # global_functions_inv maps body ids to global value names.
+        self.global_functions_inv = {}
+        # jitted_function_aliases maps body ids to known aliases.
+        self.jitted_function_aliases = defaultdict(set)
+        self.jit_count = 0
+        self.compilation_dependencies = {}
+        self.cache = {}
+
+    def mark_entry_point(self, body_id):
+        """Marks the node with the given identifier as a function entry point."""
+        if body_id not in self.jitted_entry_points:
+            self.todo_entry_points.add(body_id)
+
+    def is_jittable_entry_point(self, body_id):
+        """Tells if the node with the given identifier is a function entry point that
+           has not been marked as non-jittable. This only returns `True` if the JIT
+           is enabled and the function entry point has been marked jittable, or if
+           the function has already been compiled."""
+        return ((body_id in self.todo_entry_points) or (body_id in self.jitted_entry_points))
+
+    def generate_name(self, infix, suggested_name=None):
+        """Generates a new name or picks the suggested name if it is still
+           available."""
+        if suggested_name is not None \
+            and suggested_name not in self.jit_globals \
+            and not keyword.iskeyword(suggested_name):
+            self.jit_count += 1
+            return suggested_name
+        else:
+            function_name = 'jit_%s%d' % (infix, self.jit_count)
+            self.jit_count += 1
+            return function_name
+
+    def generate_function_name(self, body_id, suggested_name=None):
+        """Generates a new function name or picks the suggested name if it is still
+           available."""
+        if suggested_name is None:
+            suggested_name = self.get_global_name(body_id)
+
+        return self.generate_name('func', suggested_name)
+
+    def register_global(self, body_id, global_name):
+        """Associates the given body id with the given global name."""
+        self.global_functions[global_name] = body_id
+        self.global_functions_inv[body_id] = global_name
+
+    def get_global_name(self, body_id):
+        """Gets the name of the global function with the given body id.
+           Returns None if no known global exists with the given id."""
+        if body_id in self.global_functions_inv:
+            return self.global_functions_inv[body_id]
+        else:
+            return None
+
+    def get_global_body_id(self, global_name):
+        """Gets the body id of the global function with the given name.
+           Returns None if no known global exists with the given name."""
+        if global_name in self.global_functions:
+            return self.global_functions[global_name]
+        else:
+            return None
+
+    def register_compiled(self, body_id, compiled_function, function_name=None):
+        """Registers a compiled entry point with the JIT."""
+        # Get the function's name.
+        actual_function_name = self.generate_function_name(body_id, function_name)
+        # Map the body id to the given parameter list.
+        self.jitted_entry_points[body_id] = actual_function_name
+        self.jit_globals[actual_function_name] = compiled_function
+        if function_name is not None:
+            self.register_global(body_id, function_name)
+
+        if body_id in self.todo_entry_points:
+            self.todo_entry_points.remove(body_id)
+
+    def __lookup_compiled_body_impl(self, body_id):
+        """Looks up a compiled function by body id. Returns a matching function,
+           or None if no function was found."""
+        if body_id is not None and body_id in self.jitted_entry_points:
+            return self.jit_globals[self.jitted_entry_points[body_id]]
+        else:
+            return None
+
+    def __lookup_external_body_impl(self, global_name, body_id):
+        """Looks up an external function by global name. Returns a matching function,
+           or None if no function was found."""
+        if global_name is not None and self.compiled_function_lookup is not None:
+            result = self.compiled_function_lookup(global_name)
+            if result is not None and body_id is not None:
+                self.register_compiled(body_id, result, global_name)
+
+            return result
+        else:
+            return None
+
+    def lookup_compiled_body(self, body_id):
+        """Looks up a compiled function by body id. Returns a matching function,
+           or None if no function was found."""
+        result = self.__lookup_compiled_body_impl(body_id)
+        if result is not None:
+            return result
+        else:
+            global_name = self.get_global_name(body_id)
+            return self.__lookup_external_body_impl(global_name, body_id)
+
+    def lookup_compiled_function(self, global_name):
+        """Looks up a compiled function by global name. Returns a matching function,
+           or None if no function was found."""
+        body_id = self.get_global_body_id(global_name)
+        result = self.__lookup_compiled_body_impl(body_id)
+        if result is not None:
+            return result
+        else:
+            return self.__lookup_external_body_impl(global_name, body_id)
+
+    def jit_signature(self, body_id):
+        """Acquires the signature for the given body id node, which consists of the
+           parameter variables, parameter name and a flag that tells if the given function
+           is mutable."""
+        if body_id not in self.jitted_parameters:
+            signature_id, = yield [("RRD", [body_id, "body"])]
+            signature_id = signature_id[0]
+            param_set_id, is_mutable = yield [
+                ("RD", [signature_id, "params"]),
+                ("RD", [signature_id, "mutable"])]
+            if param_set_id is None:
+                self.jitted_parameters[body_id] = ([], [], is_mutable)
+            else:
+                param_name_ids, = yield [("RDK", [param_set_id])]
+                param_names = yield [("RV", [n]) for n in param_name_ids]
+                #NOTE Patch up strange links...
+                param_names = [i for i in param_names if i is not None]
+                param_vars = yield [("RD", [param_set_id, k]) for k in param_names]
+
+                #NOTE that variables might not be in the correct order, as we just read them out!
+                lst = sorted([(name, var) for name, var in zip(param_names, param_vars)])
+                param_vars = [i[1] for i in lst]
+                param_names = [i[0] for i in lst]
+                self.jitted_parameters[body_id] = (param_vars, param_names, is_mutable)
+
+        yield [("RETURN", [self.jitted_parameters[body_id]])]
+
+    def check_jittable(self, body_id, suggested_name=None):
+        """Checks if the function with the given body id is obviously non-jittable. If it's
+           non-jittable, then a `JitCompilationFailedException` exception is thrown."""
+        if body_id is None:
+            raise ValueError('body_id cannot be None: ' + suggested_name)
+
+    def jit_define_function(self, function_name, function_def):
+        """Converts the given tree-IR function definition to Python code, defines it,
+           and extracts the resulting function."""
+        # The comment below makes pylint shut up about our (hopefully benign) use of exec here.
+        # pylint: disable=I0011,W0122
+        if self.jit_code_log_function is not None:
+            self.jit_code_log_function(function_def)
+
+        # Convert the function definition to Python code, and compile it.
+        code_generator = tree_ir.PythonGenerator()
+        function_def.generate_python_def(code_generator)
+        source_map_name = self.get_source_map_name(function_name)
+        if source_map_name is not None:
+            self.jit_globals[source_map_name] = code_generator.source_map_builder.source_map
+        exec(str(code_generator), self.jit_globals)
+
+        # Extract the compiled function from the JIT global state.
+        return self.jit_globals[function_name]
+
+    def jit_delete_function(self, function_name):
+        """Deletes the function with the given function name."""
+        del self.jit_globals[function_name]
+import modelverse_kernel.primitives as primitive_functions
+
+class JitCompilationFailedException(Exception):
+    """A type of exception that is raised when the jit fails to compile a function."""
+    pass

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1061
kernel/modelverse_kernel/legacy.py


+ 411 - 126
kernel/modelverse_kernel/main.py

@@ -1,10 +1,7 @@
 import modelverse_kernel.primitives as primitive_functions
 import modelverse_kernel.compiled as compiled_functions
 from modelverse_kernel.request_handler import RequestHandler
-import modelverse_jit.jit as jit
-import modelverse_jit.intrinsics as jit_intrinsics
-import modelverse_jit.jit_primitives as jit_primitives
-import modelverse_jit.runtime as jit_runtime
+import modelverse_kernel.jit as jit
 from collections import defaultdict
 import sys
 import time
@@ -15,6 +12,9 @@ else:
     string_types = (str, unicode)
 
 class ModelverseKernel(object):
+    
+    counter = 0
+
     def __init__(self, root):
         self.root = root
         self.returnvalue = None
@@ -29,76 +29,72 @@ class ModelverseKernel(object):
         #
         self.request_handlers = {}
         self.allow_compiled = True
-        #self.allow_compiled = False
-
-        # Set `self.suggest_function_names` to True to associate global function names
-        # with their function bodies.
-        self.suggest_function_names = True
 
         # `self.jit` handles most JIT-related functionality.
         self.jit = jit.ModelverseJit()
-        if self.allow_compiled:
-            self.jit.compiled_function_lookup = lambda func_name: \
-                getattr(compiled_functions, func_name, None)
-
-        jit_intrinsics.register_intrinsics(self.jit)
-
-        # To disable the JIT, uncomment the line below:
-        #
-        #     self.jit.set_jit_enabled(False)
-        #
-        # To disable direct calls in the JIT, uncomment the line below:
-        #
-        #     self.jit.allow_direct_calls(False)
-        #
-        # To disable thunks in the JIT, uncomment the line below:
-        #
-        #     self.jit.enable_thunks(False)
-        #
-        # To make the JIT compile 'input' instructions as calls to
-        # modelverse_jit.runtime.get_input, uncomment the line below:
-        #
-        #     self.jit.use_input_function()
-        #
-        # To disable source maps in the JIT, uncomment the line below:
-        #
-        #     self.jit.enable_source_maps(False)
-        #
-        # To enable tracing in the JIT (for debugging purposes), uncomment
-        # the line below:
-        #
-        # self.jit.enable_tracing()
-        #
-        # To make the JIT print JIT successes and errors to the command-line,
-        # uncomment the line below:
-        #
-        #     self.jit.set_jit_success_log()
-        #
-        # If you want, you can use a custom logging function:
-        #
-        #     self.jit.set_jit_success_log(logging_function)
-        #
-        # To make the JIT print jitted code to the command-line, uncomment the
-        # line below:
-        #
-        # self.jit.set_jit_code_log()
-        #
-        # If you want, you can use a custom logging function:
-        #
-        #     self.jit.set_jit_code_log(logging_function)
-        #
+        self.jit.compiled_function_lookup = lambda func_name : getattr(compiled_functions, func_name, None)
+        self.jit.body_cache = {}
 
         self.debug_info = defaultdict(list)
 
+    def try_to_protect(self, var):
+        if isinstance(var, dict) and "id" in var and var['id'] is not None:
+            return set([var['id']])
+        elif type(var) == int:
+            return set([var])
+        elif isinstance(var, dict):
+            protect = set()
+            for v in var.values():
+                protect |= self.try_to_protect(v)
+            return protect
+        elif isinstance(var, list):
+            protect = set()
+            for v in var:
+                protect |= self.try_to_protect(v)
+            return protect
+        elif isinstance(var, set):
+            protect = set()
+            for v in var:
+                protect |= self.try_to_protect(v)
+            return protect
+        return set()
+
+    def protect_temporary_variables(self, taskname):
+        generators = []
+        for h in self.request_handlers.values():
+            for handler in h.values():
+                for generator in handler.generator_stack:
+                    generators.append(generator)
+
+        to_protect = set()
+        for gen in generators:
+            try:
+                variables = gen.gi_frame.f_locals
+                for var in variables.values():
+                    to_protect |= self.try_to_protect(var)
+            except:
+                pass
+
+        # Create the node to which everything is attached
+        self.fixed_node, = yield [("CN", [])]
+        yield [("CE", [self.root, self.fixed_node])]
+        yield [("CE", [self.fixed_node, node]) for node in to_protect]
+        yield [("RETURN", [None])]
+
+    def unprotect_temporary_variables(self, taskname):
+        yield [("DN", [self.fixed_node])]
+        yield [("RETURN", [None])]
+
     def execute_yields(self, taskname, operation, params, reply):
         self.taskname = taskname
         if taskname not in self.request_handlers:
             self.request_handlers[taskname] = {}
+            self.jit.cache.setdefault(taskname, {})
         if operation not in self.request_handlers[taskname]:
             # Create the generator for the function to execute
             self.request_handlers[taskname][operation] = RequestHandler()
         handler = self.request_handlers[taskname][operation]
-        if not handler.is_active():
+        if len(handler.generator_stack) == 0:
             handler.push_generator(getattr(self, operation)(taskname, *params))
 
         return handler.handle_request(reply)
@@ -124,15 +120,11 @@ class ModelverseKernel(object):
             if self.phase_v == "finish":
                 gen = self.helper_init(task_root)
             elif self.inst is None:
-                print("No instruction pointer found...")
-                print(locals())
-                print("Phase: " + str(self.phase_v))
-                print("Debug: " + str(self.debug_info[taskname]))
                 raise Exception("Instruction pointer could not be found!")
             elif isinstance(self.phase_v, string_types):
                 if self.phase_v == "init" and self.jit.is_jittable_entry_point(self.inst):
                     #print("%-30s(%s)" % ("COMPILED " + str(self.jit.jitted_entry_points[self.inst]), phase_v))
-                    gen = self.execute_jit(task_root, self.inst, taskname)
+                    gen = self.execute_jit(task_root, self.inst, taskname, store=True, resolve=False)
                 elif inst_v is None:
                     raise Exception("%s: error understanding command (%s, %s)" % (self.debug_info[taskname], inst_v, self.phase_v))
                 else:
@@ -146,15 +138,9 @@ class ModelverseKernel(object):
             else:
                 raise Exception("%s: error understanding command (%s, %s)" % (self.debug_info[taskname], inst_v, self.phase_v))
 
-            def handle_jit_failed(exception):
-                # Try again, but this time without the JIT.
-                gen = self.get_inst_phase_generator(inst_v, self.phase_v, task_root)
-                yield [("TAIL_CALL", [gen])]
-
-            yield [("TRY", [])]
-            yield [("CATCH", [jit.JitCompilationFailedException, handle_jit_failed])]
             yield [("CALL", [gen])]
-            yield [("END_TRY", [])]
+
+        yield [("FINISH", [])]
 
     def get_inst_phase_generator(self, inst_v, phase_v, task_root):
         """Gets a generator for the given instruction in the given phase,
@@ -166,10 +152,8 @@ class ModelverseKernel(object):
     ### Process primitives ###
     ##########################
     def load_primitives(self, taskname):
-        yield [("CALL_ARGS",
-                [self.load_primitives_from, (taskname, 'primitives', primitive_functions)])]
-        yield [("CALL_ARGS",
-                [self.load_primitives_from, (taskname, 'jit', jit_primitives)])]
+        yield [("CALL_ARGS", [self.load_primitives_from, (taskname, 'primitives', primitive_functions)])]
+        yield [("FINISH", [])]
 
     def load_primitives_from(self, taskname, source_name, source):
         hierarchy, = yield [("RD", [self.root, "__hierarchy"])]
@@ -179,66 +163,339 @@ class ModelverseKernel(object):
         signatures = yield [("RDN", [primitives, f]) for f in keys]
         bodies = yield [("RD", [f, "body"]) for f in signatures]
         for i in range(len(keys)):
-            self.jit.register_compiled(
-                bodies[i],
-                getattr(source, function_names[i]),
-                function_names[i])
-
-    def jit_compile(self, task_root, inst):
-        # Try to retrieve the suggested name.
-        suggested_name = self.jit.get_global_name(inst)
-        # Have the JIT compile the function.
-        return self.jit.jit_compile(task_root, inst, suggested_name)
+            self.jit.register_compiled(bodies[i], getattr(source, function_names[i]), function_names[i])
+        yield [("RETURN", [None])]
+
+    def print_instruction(self, inst, indent, nested_indent=None):
+        """
+        intrinsics = {"integer_addition": (lambda x, y: "(%s + %s)" % (x, y)),
+                      "string_join": (lambda x, y: "(str(%s) + str(%s))" % (x, y)),
+                      }
+        """
+        intrinsics = {}
+
+        if nested_indent is None:
+            nested_indent = indent
+
+        inst_type, = yield [("RV", [inst])]
+        instruction = "(no_printer_for_%s)" % inst_type["value"]
+        prev = ""
+
+        if inst_type["value"] == "if":
+            cond, true, false = yield [("RD", [inst, "cond"]),
+                                       ("RD", [inst, "then"]),
+                                       ("RD", [inst, "else"])]
+            (prev_cond, instruction_cond), = yield [("CALL_ARGS", [self.print_instruction, (cond, 0, indent)])]
+            (prev_true, instruction_true), = yield [("CALL_ARGS", [self.print_instruction, (true, indent+1)])]
+            if false:
+                (prev_false, instruction_false), = yield [("CALL_ARGS", [self.print_instruction, (false, indent+1)])]
+                false = ("  " * indent + "else:\n%s%s") % (prev_false, instruction_false)
+            else:
+                false = ""
+
+            instruction = prev_cond + \
+                            "  " * indent + "if 'value' not in %s:\n" % instruction_cond + \
+                            "  " * (indent + 1) + "%s['value'], = yield [('RV', [%s['id']])]\n" % (instruction_cond, instruction_cond) + \
+                            "  " * indent + "if (%s['value']):\n" % instruction_cond + \
+                                prev_true + \
+                                instruction_true + \
+                                false
+
+        elif inst_type["value"] == "constant":
+            node, = yield [("RD", [inst, "node"])]
+            node_value, = yield [("RV", [node])]
+            if node_value is not None:
+                # There is a value to the node, so replicate the value
+                if isinstance(node_value, string_types):
+                    value = '"%s"' % node_value.replace('"', '\\"').replace("'", "\\'").replace('\t', '\\t').replace('\n', '\\n')
+                else:
+                    value = str(node_value)
+                instruction = "constant_" + str(ModelverseKernel.counter)
+                ModelverseKernel.counter += 1
+                prev = "  " * nested_indent + instruction + " = {'value': " + value + "}\n"
+            else:
+                # Node is None, meaning that it was not about the value, but the node itself...
+                instruction = "{'id': %s}" % str(node)
+
+        elif inst_type["value"] == "return":
+            value, = yield [("RD", [inst, "value"])]
+            if value:
+                (prev_value, instruction_value), = yield [("CALL_ARGS", [self.print_instruction, (value, 0, indent)])]
+                instruction = prev_value + "  " * indent + "yield [('RETURN', [%s])]\n" % instruction_value
+            else:
+                instruction = "  " * indent + "yield [('RETURN', [None])]\n"
+
+        elif inst_type["value"] == "declare":
+            instruction = ""
+
+        elif inst_type["value"] == "global":
+            instruction = ""
+
+        elif inst_type["value"] == "break":
+            instruction = "  " * indent + "break\n"
+
+        elif inst_type["value"] == "continue":
+            instruction = "  " * indent + "continue\n"
+
+        elif inst_type["value"] == "input":
+            prev = "  " * nested_indent + "_inputs, = yield [('RD', [_root, 'input'])]\n" + \
+                   "  " * nested_indent + "val, val_e, nxt = yield [('RD', [_inputs, 'value']), ('RDE', [_inputs, 'value']), ('RD', [_inputs, 'next'])]\n" + \
+                   "  " * nested_indent + "_, val_e = yield [('DE', [val_e]), ('RDE', [_root, 'input'])]\n" + \
+                   "  " * nested_indent + "yield [('CD', [_root, 'input', nxt]), ('DE', [val_e])]\n" + \
+                   "  " * nested_indent + "_result = {'id': val}\n"
+
+            instruction = "_result"
+
+        elif inst_type["value"] == "output":
+            value, = yield [("RD", [inst, "value"])]
+            (prev, instruction), = yield [("CALL_ARGS", [self.print_instruction, (value, 0, indent)])]
+            instruction = prev + \
+                          "  " * indent + "if 'id' not in %s:\n" % instruction + \
+                          "  " * (indent + 1) + "%s['id'], = yield [('CNV', [%s['value']])]\n" % (instruction, instruction) + \
+                          "  " * indent + "_outputs, _outputs_e = yield [('RD', [_root, 'last_output']), ('RDE', [_root, 'last_output'])]\n" + \
+                          "  " * indent + "_, _new = yield [('CD', [_outputs, 'value', %s['id']]), ('CN', [])]\n" % instruction + \
+                          "  " * indent + "yield [('CD', [_outputs, 'next', _new]), ('DE', [_outputs_e]), ('CD', [_root, 'last_output', _new])]\n"
+
+        elif inst_type["value"] == "resolve":
+            value, = yield [("RD", [inst, "var"])]
+            str_value, = yield [("RV", [value])]
+            if str_value:
+                # Is a global
+                prev = \
+                       "  " * nested_indent + "%s = _mvk.jit.cache[_taskname].get('%s', None)\n" % (str_value, str_value) + \
+                       "  " * nested_indent + "if %s is None:\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) + "%s = {'id': %s}\n" % (str_value, str_value) + \
+                       "  " * (nested_indent + 1) + "_mvk.jit.cache[_taskname]['%s'] = %s\n" % (str_value, str_value)
+                instruction = str_value
+
+                if self.jit.get_global_body_id(str_value) is None:
+                    val, = yield [("RD", [self.root, self.taskname])]
+                    val, = yield [("RD", [val, 'globals'])]
+                    val, = yield [("RD", [val, str_value])]
+                    val, = yield [("RD", [val, 'value'])]
+                    val, = yield [("RD", [val, 'body'])]
+
+                    self.jit.register_global(val, str_value)
+            else:
+                # Is a local
+                instruction = "var_%s" % value
+
+        elif inst_type["value"] == "assign":
+            var, val = yield [("RD", [inst, "var"]),
+                              ("RD", [inst, "value"])]
+            (prev_var, instruction_var), = yield [("CALL_ARGS", [self.print_instruction, (var, 0, indent)])]
+            (prev_val, instruction_val), = yield [("CALL_ARGS", [self.print_instruction, (val, 0, indent)])]
+
+            instruction = prev_val + "  " * indent + instruction_var + " = " + instruction_val + "\n"
+
+            if prev_var:
+                # Got something to do before the variable is usable, so this is a global!
+                # Therefore we actually do the operation in the Modelverse as well!
+                instruction += \
+                       "  " * nested_indent + "_var, = yield [('RD', [_globs, '%s'])]\n" % instruction_var + \
+                       "  " * nested_indent + "if _var is None:\n" + \
+                       "  " * (nested_indent + 1) + "_var, = yield [('CN', [])]\n" + \
+                       "  " * (nested_indent + 1) + "yield [('CD', [_globs, '%s', _var])]\n" % instruction_var + \
+                       "  " * nested_indent + "_old_edge, = yield [('RDE', [_var, 'value'])]\n" + \
+                       "  " * nested_indent + "if 'id' not in %s:\n" % instruction_var + \
+                       "  " * (nested_indent + 1) + "%s['id'], = yield [('CNV', [%s['value']])]\n" % (instruction_var, instruction_var) + \
+                       "  " * nested_indent + "yield [('CD', [_var, 'value', %s['id']]), ('DE', [_old_edge])]\n" % instruction_var + \
+                       "  " * nested_indent + "_mvk.jit.cache[_taskname]['%s'] = %s\n" % (instruction_var, instruction_var)
+
+        elif inst_type["value"] == "call":
+            func_name, = yield [("RD", [inst, "func"])]
+            (prev_func_name, func_name), = yield [("CALL_ARGS", [self.print_instruction, (func_name, nested_indent, nested_indent)])]
+            param_list = {}
+
+            param, = yield [("RD", [inst, "params"])]
+            computation = ""
+            while param:
+                value, name = yield [("RD", [param, "value"]), ("RD", [param, "name"])]
+                name, = yield [("RV", [name])]
+                (prev_res, instruction_res), = yield [("CALL_ARGS", [self.print_instruction, (value, 0, nested_indent)])]
+                param, = yield [("RD", [param, "next_param"])]
+                computation += prev_res
+                param_list[name] = instruction_res
+
+            value = "func_result_" + str(ModelverseKernel.counter)
+            ModelverseKernel.counter += 1
+
+            param_list = "{" + ", ".join(["'%s': %s" % (k, v) for k, v in param_list.items()]) + "}"
+            actual_computation = "$$INDENT$$%s, = yield [('CALL_ARGS', [_mvk.execute_jit, (_root, %s['id'], _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 + actual_computation.replace("$$INDENT$$", "  " * nested_indent), 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, actual_computation.replace("$$INDENT$$", "  " * indent)
+
+        elif inst_type["value"] == "access":
+            value, = yield [("RD", [inst, "var"])]
+            (prev, instruction), = yield [("CALL_ARGS", [self.print_instruction, (value, 0, nested_indent)])]
+
+        elif inst_type["value"] == "while":
+            cond, body = yield [("RD", [inst, "cond"]),
+                                ("RD", [inst, "body"])]
+            (prev_cond, instruction_cond), = yield [("CALL_ARGS", [self.print_instruction, (cond, 0, indent+1)])]
+            (prev_body, instruction_body), = yield [("CALL_ARGS", [self.print_instruction, (body, indent+1)])]
+            instruction = "  " * indent + "__counter_%s = 0\n" % inst + \
+                          "  " * indent + "while 1:\n" + prev_cond + \
+                          "  " * (indent + 1) + "if 'value' not in %s:\n" % instruction_cond + \
+                          "  " * (indent + 2) + "%s['value'], = yield [('RV', [%s['id']])]\n" % (instruction_cond, instruction_cond) + \
+                          "  " * (indent + 1) + "if not (%s['value']):\n" % instruction_cond + \
+                          "  " * (indent + 2) + "break\n" + \
+                          "  " * (indent + 1) + "else:\n" + \
+                          "  " * (indent + 2) + "__counter_%s += 1\n" % inst + \
+                          "  " * (indent + 2) + "if __counter_%s > 20:\n" % inst + \
+                          "  " * (indent + 3) + "yield None\n" + \
+                          "  " * (indent + 3) + "__counter_%s = 0\n" % inst + \
+                          prev_body + instruction_body
+
+
+        next_inst, = yield [("RD", [inst, "next"])]
+        if next_inst:
+            (prev_next, inst_next), = yield [("CALL_ARGS", [self.print_instruction, (next_inst, indent)])]
+            next_inst = prev_next + inst_next
+        else:
+            next_inst = ""
+
+        yield [('RETURN', [(prev, instruction + next_inst)])]
+
+    def read_function(self, inst, suggested_name):
+        initial_instruction = inst
+
+        (params, _, is_mutable), = yield [("CALL_ARGS", [self.jit.jit_signature, (inst,)])]
+        if is_mutable:
+            print("Ignoring mutable or unreadable: %s" % suggested_name)
+            raise jit.JitCompilationFailedException("FAIL")
+
+        #print("Reading function: %s" % suggested_name)
+        (prev, printed), = yield [("CALL_ARGS", [self.print_instruction, (inst, 1)])]
+        preamble = "  _mvk = kwargs['mvk']\n" + \
+                   "  _root = kwargs['task_root']\n" + \
+                   "  _taskname = kwargs['taskname']\n" + \
+                   "  _globs = _mvk.jit.cache[_taskname].get('_globs', None)\n" + \
+                   "  if _globs is None:\n" + \
+                   "    _globs, = yield [('RD', [kwargs['task_root'], 'globals'])]\n" + \
+                   "    _mvk.jit.cache[_taskname]['_globs'] = _globs\n"
+        printed = preamble + prev + printed
+        #print("Total printed function: ")
+        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
+        else:
+            func = "def " + suggested_name + "(**kwargs):\n" + printed
+        
+        #print(func)
 
-    def execute_jit(self, task_root, inst, taskname):
-        # execute_jit
-        task_frame, =    yield [("RD", [task_root, "frame"])]
-        symbols, =       yield [("RD", [task_frame, "symbols"])]
-        dict_keys_ref, =  yield [("RDK", [symbols])]
-        dict_keys_ref_n =   yield [("RD", [i, "name"]) for i in dict_keys_ref]
-        dict_keys =       yield [("RV", [i]) for i in dict_keys_ref_n]
-        dict_values_elem = yield [("RDN", [symbols, i]) for i in dict_keys_ref]
-        dict_values = yield [("RD", [i, "value"]) for i in dict_values_elem]
+        # To write out all generated functions
+        #with open('/tmp/junk/%s' % suggested_name, 'w') as f:
+        #    f.write(func)
 
-        parameters = dict(list(zip(dict_keys, dict_values)))
+        yield [("RETURN", [func])]
 
-        parameters["root"] = self.root
-        parameters["task_root"] = task_root
-        parameters["taskname"] = taskname
-        parameters["mvk"] = self
+    def execute_jit(self, task_root, inst, taskname, params = {}, store=False, resolve=True):
+        # execute_jit
+        if resolve:
+            try:
+                inst = self.jit.body_cache[inst]
+            except KeyError:
+                body, = yield [("RD", [inst, "body"])]
+                self.jit.body_cache[inst] = body
+                inst = body
+
+        if store:
+            task_frame, =    yield [("RD", [task_root, "frame"])]
+            symbols, =       yield [("RD", [task_frame, "symbols"])]
+            dict_keys_ref, =  yield [("RDK", [symbols])]
+            if dict_keys_ref:
+                dict_keys_ref_n =   yield [("RD", [i, "name"]) for i in dict_keys_ref]
+                dict_keys =       yield [("RV", [i]) for i in dict_keys_ref_n]
+                dict_values_elem = yield [("RDN", [symbols, i]) for i in dict_keys_ref]
+                dict_values = yield [("RD", [i, "value"]) for i in dict_values_elem]
+
+                parameters = dict(zip(dict_keys, dict_values))
+                parameters.update(params)
+
+                for p in parameters.keys():
+                    if not isinstance(parameters[p], dict):
+                        parameters[p] = {'id': parameters[p]}
+                params = parameters
+                    
+        params["root"] = self.root
+        params["task_root"] = task_root
+        params["taskname"] = taskname
+        params["mvk"] = self
 
         # Have the JIT compile the function.
-        compiled_func, = yield [("CALL_ARGS", [self.jit_compile, (task_root, inst)])]
+        if inst is None:
+            suggested_name = self.jit.get_global_name(inst)
+            if suggested_name is None:
+                suggested_name = "func_%s" % str(inst)
+            raise ValueError('body_id cannot be None: ' + str(suggested_name))
+
+        elif inst in self.jit.jitted_entry_points:
+            compiled_func = self.jit.jit_globals[self.jit.jitted_entry_points[inst]]
+        else:
+            compiled_func = self.jit.lookup_compiled_body(inst)
+
+            if compiled_func is None:
+                suggested_name = self.jit.get_global_name(inst)
+                if suggested_name is None:
+                    suggested_name = "func_%s" % str(inst)
+                compiled_func, = yield [("CALL_ARGS", [self.read_function, (inst, suggested_name)])]
+                compiled_func = self.merge_function(compiled_func, suggested_name)
+                self.jit.register_compiled(inst, compiled_func, suggested_name)
+
         # Run the compiled function.
-        results = yield [("CALL_KWARGS", [compiled_func, parameters])]
+        results = yield [("CALL_KWARGS", [compiled_func, params])]
         if results is None:
-            raise Exception(
-                "%s: primitive finished without returning a value!" % (self.debug_info[taskname]))
+            raise Exception("%s: primitive finished without returning a value!" % (self.debug_info[taskname]))
         else:
             result, = results
 
-        # Clean up the current stack, as if a return happened
-        old_frame, exception_return = yield [
-            ("RD", [task_frame, "prev"]),
-            ("RD", [task_frame, primitive_functions.EXCEPTION_RETURN_KEY])]
+        #print("Got result: " + str(result))
+        if result is None:
+            result = {'id': None, 'value': None}
 
-        if self.debug_info[self.taskname]:
-            self.debug_info[self.taskname].pop()
+        if store:
+            # Clean up the current stack, as if a return happened
+            old_frame, exception_return = yield [
+                ("RD", [task_frame, "prev"]),
+                ("RD", [task_frame, primitive_functions.EXCEPTION_RETURN_KEY])]
+
+            #if self.debug_info[self.taskname]:
+            #    self.debug_info[self.taskname].pop()
+
+            if "id" not in result:
+                result['id'], = yield [("CNV", [result['value']])]
+
+            if exception_return is not None:
+                # The caller has requested that we throw an exception instead of injecting
+                # the return value into the caller's frame. Read the comment at
+                # primitive_functions.EXCEPTION_RETURN_KEY for the rationale behind this design.
+                yield [("CD", [task_root, "frame", old_frame]),
+                       ("DN", [task_frame])]
+                raise primitive_functions.InterpretedFunctionFinished(result)
+            else:
+                lnk, =          yield [("RDE", [old_frame, "returnvalue"])]
+                _, _, _, _ =    yield [("CD", [old_frame, "returnvalue", result['id']]),
+                                       ("CD", [task_root, "frame", old_frame]),
+                                       ("DE", [lnk]),
+                                       ("DN", [task_frame]),
+                                      ]
 
-        if exception_return is not None:
-            # The caller has requested that we throw an exception instead of injecting
-            # the return value into the caller's frame. Read the comment at
-            # primitive_functions.EXCEPTION_RETURN_KEY for the rationale behind this design.
-            yield [("CD", [task_root, "frame", old_frame]),
-                   ("DN", [task_frame])]
-            raise primitive_functions.InterpretedFunctionFinished(result)
         else:
-            lnk, =          yield [("RDE", [old_frame, "returnvalue"])]
-            _, _, _, _ =    yield [("CD", [old_frame, "returnvalue", result]),
-                                   ("CD", [task_root, "frame", old_frame]),
-                                   ("DE", [lnk]),
-                                   ("DN", [task_frame]),
-                                  ]
+            yield [("RETURN", [result])]
+        yield [("RETURN", [None])]
+
+    def merge_function(self, func, name):
+        exec(func, self.jit.jit_globals)
+        return self.jit.jit_globals[name]
 
     ########################################
     ### Execute input and output methods ###
@@ -261,6 +518,8 @@ class ModelverseKernel(object):
 
             self.returnvalue = rv_value
             self.success = True
+            #print("OUTPUT: (%s, %s)" % (taskname, self.returnvalue))
+        yield [("FINISH", [])]
 
     def set_input(self, taskname, value):
         task_root, =        yield [("RD", [self.root, taskname])]
@@ -275,7 +534,9 @@ class ModelverseKernel(object):
                                    ("CD", [old_input, "value", new_value]),
                                    ("DE", [link])
                                   ]
+        #print("INPUT: (%s, %s)" % (taskname, value))
         self.returnvalue = {"id": 100, "value": "success"}
+        yield [("FINISH", [])]
 
     #############################################
     ### Transformation rules for instructions ###
@@ -323,6 +584,7 @@ class ModelverseKernel(object):
                                    ("DE", [old_phase_link]),
                                    ("DE", [old_evalstack_phase_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def break_init(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -366,6 +628,7 @@ class ModelverseKernel(object):
                                    ("DE", [old_phase_link]),
                                    ("DE", [old_evalstack_phase_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def if_init(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -390,6 +653,7 @@ class ModelverseKernel(object):
                                    ("DE", [evalstack_link]),
                                    ("DE", [ip_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def if_cond(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -452,6 +716,7 @@ class ModelverseKernel(object):
                                    ("DE", [ip_link]),
                                    ("DE", [phase_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def while_init(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -475,6 +740,7 @@ class ModelverseKernel(object):
                                    ("DE", [evalstack_link]),
                                    ("DE", [ip_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def while_cond(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -519,6 +785,7 @@ class ModelverseKernel(object):
             _, _ =          yield [("CD", [task_frame, "phase", new_phase]),
                                    ("DE", [phase_link])
                                   ]
+        yield [("RETURN", [None])]
 
     def access_init(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -542,6 +809,7 @@ class ModelverseKernel(object):
                                    ("DE", [evalstack_link]),
                                    ("DE", [ip_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def access_eval(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -558,6 +826,7 @@ class ModelverseKernel(object):
                                    ("DE", [phase_link]),
                                    ("DE", [returnvalue_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def resolve_init(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -587,7 +856,7 @@ class ModelverseKernel(object):
                 print("Globals: " + str(globs))
                 globs = yield [("RV", [i]) for i in globs]
                 print("Resolved globals: " + str(globs))
-                raise Exception(jit_runtime.GLOBAL_NOT_FOUND_MESSAGE_FORMAT % var_name)
+                raise Exception(jit.GLOBAL_NOT_FOUND_MESSAGE_FORMAT % var_name)
 
             # Resolved a global, so this is a string
             # Potentially, this might even be a function that we have precompiled already!
@@ -604,7 +873,7 @@ class ModelverseKernel(object):
 
             # If we're dealing with a function, then we might want to figure out what its body id
             # is now so we can suggest a name to the JIT later.
-            if self.suggest_function_names and self.jit.get_global_body_id(var_name) is None:
+            if self.jit.get_global_body_id(var_name) is None:
                 compiler_val, = yield [("RD", [variable, "value"])]
                 if compiler_val is not None:
                     compiler_body, = yield [("RD", [compiler_val, "body"])]
@@ -622,6 +891,7 @@ class ModelverseKernel(object):
                                    ("DE", [phase_link]),
                                    ("DE", [returnvalue_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def assign_init(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -645,6 +915,7 @@ class ModelverseKernel(object):
                                    ("DE", [evalstack_link]),
                                    ("DE", [ip_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def assign_value(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -675,6 +946,7 @@ class ModelverseKernel(object):
                                    ("DE", [phase_link]),
                                    ("DE", [ip_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def assign_assign(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -694,6 +966,7 @@ class ModelverseKernel(object):
                                    ("DE", [value_link]),
                                    ("DE", [phase_link]),
                                   ]
+        yield [("RETURN", [None])]
                     
     def return_init(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -736,6 +1009,7 @@ class ModelverseKernel(object):
                                    ("DE", [evalstack_link]),
                                    ("DE", [ip_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def return_eval(self, task_root):
         if self.debug_info[self.taskname]:
@@ -765,6 +1039,7 @@ class ModelverseKernel(object):
                 ("CD", [prev_frame, "returnvalue", returnvalue]),
                 ("DE", [old_returnvalue_link]),
                 ("DN", [task_frame])]
+        yield [("RETURN", [None])]
 
     def constant_init(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -781,6 +1056,7 @@ class ModelverseKernel(object):
                                    ("DE", [returnvalue_link]),
                                    ("DE", [phase_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def helper_init(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -821,6 +1097,7 @@ class ModelverseKernel(object):
                                    ("DE", [ip_link]),
                                    ("DE", [phase_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def call_init(self, task_root):
         task_frame, =       yield [("RD", [task_root, "frame"])]
@@ -860,6 +1137,7 @@ class ModelverseKernel(object):
                                    ("DE", [evalstack_link]),
                                    ("DE", [ip_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def call_call(self, task_root):
         self.debug_info[self.taskname].append("None")
@@ -933,6 +1211,7 @@ class ModelverseKernel(object):
                                    ("DE", [frame_link]),
                                    ("DE", [phase_link]),
                                   ]
+        yield [("RETURN", [None])]
 
     def find_overlapping(self, a, b):
         newer_frames = set(a)
@@ -1071,6 +1350,7 @@ class ModelverseKernel(object):
                                ("DE", [ip_link]),
                                ("DE", [evalstack_link]),
                               ]
+        yield [("RETURN", [None])]
 
     def input_init(self, task_root):
         task_frame, =   yield [("RD", [task_root, "frame"])]
@@ -1103,6 +1383,7 @@ class ModelverseKernel(object):
             self.input_value = None
             ex = primitive_functions.SleepKernel(0.1, True)
             raise ex
+        yield [("RETURN", [None])]
 
     def output_init(self, task_root):
         task_frame, =   yield [("RD", [task_root, "frame"])]
@@ -1126,6 +1407,7 @@ class ModelverseKernel(object):
                                ("DE", [evalstack_link]),
                                ("DE", [ip_link]),
                               ]
+        yield [("RETURN", [None])]
 
     def output_output(self, task_root):
         task_frame, =   yield [("RD", [task_root, "frame"])]
@@ -1146,6 +1428,7 @@ class ModelverseKernel(object):
                                ("DE", [last_output_link]),
                                ("DE", [phase_link]),
                               ]
+        yield [("RETURN", [None])]
 
     def declare_init(self, task_root):
         task_frame, =   yield [("RD", [task_root, "frame"])]
@@ -1166,6 +1449,7 @@ class ModelverseKernel(object):
         _, _ =          yield [("CD", [task_frame, "phase", new_phase]),
                                ("DE", [phase_link]),
                               ]
+        yield [("RETURN", [None])]
 
     def global_init(self, task_root):
         task_frame, =   yield [("RD", [task_root, "frame"])]
@@ -1189,3 +1473,4 @@ class ModelverseKernel(object):
         _, _ =          yield [("CD", [task_frame, "phase", new_phase]),
                                ("DE", [phase_link])
                               ]
+        yield [("RETURN", [None])]

+ 251 - 219
kernel/modelverse_kernel/primitives.py

@@ -2,12 +2,6 @@ import time as python_time
 import json
 import sys
 
-class PrimitiveFinished(Exception):
-    """Exception to indicate the result value of a primitive, as a return cannot be used."""
-    def __init__(self, value):
-        Exception.__init__(self)
-        self.result = value
-
 class InterpretedFunctionFinished(Exception):
     """Exception to indicate the result value of an interpreted function, as a return
        cannot be used."""
@@ -23,7 +17,6 @@ class SleepKernel(Exception):
         self.interruptable = interruptable
 
 # Functions annotated with __exception_return use the JIT's calling convention instead of
-# the kernel's: returns are handled by throwing a PrimitiveFinished exception; the caller's
 # returnvalue is not modified.
 #
 # ### Rationale for __exception_return
@@ -42,359 +35,398 @@ EXCEPTION_RETURN_KEY = "__exception_return"
    exception with the return value instead of injecting the return value in the caller's frame."""
 
 def integer_subtraction(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value - b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] - b['value']}])]
 
 def integer_addition(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value + b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] + b['value']}])]
 
 def integer_multiplication(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value * b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] * b['value']}])]
 
 def integer_division(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [int(a_value) // b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': int(a['value']) // b['value']}])]
 
 def integer_lt(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value < b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] < b['value']}])]
 
 def bool_and(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value and b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] and b['value']}])]
 
 def bool_or(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value or b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] or b['value']}])]
 
 def bool_not(a, **remainder):
-    a_value, =          yield [("RV", [a])]
-    result, = yield [("CNV", [not a_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    yield [("RETURN", [{'value': not a['value']}])]
 
 def float_subtraction(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value - b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] - b['value']}])]
 
 def float_addition(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value + b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] + b['value']}])]
 
 def float_multiplication(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value * b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] * b['value']}])]
 
 def float_division(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [float(a_value) / float(b_value)])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': float(a['value']) / b['value']}])]
 
 def float_lt(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value < b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] < b['value']}])]
 
 def string_join(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [str(a_value) + str(b_value)])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': str(a['value']) + str(b['value'])}])]
 
 def string_split(a, b, **remainder):
     # TODO make non-primitive, though compiled
-    a_value, b_value = yield [("RV", [a]), ("RV", [b])]
-    result = a_value.split(b_value)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    result = a['value'].split(b['value'])
     elems = yield [("CN", [])] + [("CNV", [v]) for v in result]
     new_val = elems[0]
     yield [("CD", [new_val, i, v]) for i, v in enumerate(elems[1:])]
-    raise PrimitiveFinished(new_val)
+    yield [("RETURN", [{'id': new_val}])]
 
 def string_get(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value[b_value]])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'][b['value']]}])]
 
 def string_len(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [len(a_value)])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    yield [("RETURN", [{'value': len(a['value'])}])]
 
 def value_eq(a, b, **remainder):
-    a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
-    result, = yield [("CNV", [a_value == b_value])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if 'value' not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    yield [("RETURN", [{'value': a['value'] == b['value']}])]
 
 def element_eq(a, b, **remainder):
-    result, = yield [("CNV", [a == b])]
-    raise PrimitiveFinished(result)
+    if "id" not in a:
+        #print("MATERIALIZING A element_eq")
+        a['id'], = yield [("CNV", [a['value']])]
+    if "id" not in b:
+        #print("MATERIALIZING B element_eq")
+        b['id'], = yield [("CNV", [b['value']])]
+    yield [("RETURN", [{'value': a['id'] == b['id']}])]
 
 def cast_string(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    if isinstance(a_value, dict):
-        result, = yield [("CNV", [str(a_value["value"])])]
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if isinstance(a['value'], dict):
+        yield [("RETURN", [{'value': str(a['value']['value'])}])]
     else:
-        result, = yield [("CNV", [str(a_value)])]
-    raise PrimitiveFinished(result)
+        yield [("RETURN", [{'value': str(a['value'])}])]
 
 def cast_float(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [float(a_value)])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    yield [("RETURN", [{'value': float(a['value'])}])]
 
 def cast_boolean(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [bool(a_value)])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    yield [("RETURN", [{'value': bool(a['value'])}])]
 
 def cast_integer(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [int(a_value)])]
-    raise PrimitiveFinished(result)
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    yield [("RETURN", [{'value': int(a['value'])}])]
 
 def cast_value(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    if isinstance(a_value, dict):
-        # Action or type
-        value = a_value["value"]
+    if 'value' not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if isinstance(a['value'], dict):
+        yield [("RETURN", [{'value': str(a['value']['value'])}])]
     else:
-        value = json.dumps(a_value)
-    result, = yield [("CNV", [value])]
-    raise PrimitiveFinished(result)
+        yield [("RETURN", [{'value': json.dumps(a['value'])}])]
 
 def cast_id(a, **remainder):
-    result, = yield [("CNV", ["%s" % (a)])]
-    raise PrimitiveFinished(result)
-
-def list_insert(a, b, c, **remainder):
-    # TODO make non-primitive, though compiled
-    a_outgoing, c_value = yield [("RO", [a]), ("RV", [c])]
-    links = yield [("RD", [a, i]) for i in range(c_value, len(a_outgoing))] + \
-                  [("RDE", [a, i]) for i in range(c_value, len(a_outgoing))]
-
-    if sys.version_info[0] < 3:
-        values = links[:len(links)/2]
-        edges = links[len(links)/2:]
-    else:
-        values = links[:len(links) // 2]
-        edges = links[len(links) // 2:]
-
-    yield [("CD", [a, c_value, b])] + \
-          [("CD", [a, c_value + 1 + index, value]) for index, value in enumerate(values)] + \
-          [("DE", [i]) for i in edges]
-    raise PrimitiveFinished(a)
-
-def list_delete(a, b, **remainder):
-    # TODO make non-primitive, though compiled
-    a_outgoing, b_value = yield [("RO", [a]), ("RV", [b])]
-    links = yield [("RD", [a, i]) for i in range(b_value, len(a_outgoing))] + \
-                  [("RDE", [a, i]) for i in range(b_value, len(a_outgoing))]
-
-    if sys.version_info[0] < 3:
-        values = links[:len(links) / 2]
-        edges = links[len(links) / 2:]
-    else:
-        values = links[:len(links) // 2]
-        edges = links[len(links) // 2:]
-
-    yield [("CD", [a, b_value + index, value]) for index, value in enumerate(values[1:])] + \
-          [("DE", [i]) for i in edges]
-    raise PrimitiveFinished(a)
+    if "id" not in a:
+        #print("MATERIALIZING A cast_id")
+        a['id'], = yield [("CNV", [a['value']])]
+    yield [("RETURN", [{'value': str(a['id'])}])]
 
 def dict_add_fast(a, b, c, **remainder):
     # TODO deprecate, as dict_add is now also efficient
-    v, = yield [("RV", [b])]
-    yield [("CD", [a, v, c])]
-    raise PrimitiveFinished(a)
+    if "value" not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    if "id" not in c:
+        #print("MATERIALIZING C dict_add_fast")
+        c['id'], = yield [("CNV", [c['value']])]
+
+    yield [("CD", [a['id'], b['value'], c['id']])]
+    yield [("RETURN", [a])]
 
 def dict_delete(a, b, **remainder):
-    b_value, = yield [("RV", [b])]
-    edge, = yield [("RDE", [a, b_value])]
+    if "value" not in b:
+        b['value'], = yield [("RV", [b['id']])]
+
+    edge, = yield [("RDE", [a['id'], b['value']])]
     if edge is None:
-        print("Failed dict_delete for value '%s'!" % b_value)
-        keys, = yield [("RDK", [a])]
+        print("Failed dict_delete for value '%s'!" % b['value'])
+        keys, = yield [("RDK", [a['id']])]
         keys = yield [("RV", [i]) for i in keys]
         print("Keys: " + str(keys))
         raise Exception()
     yield [("DE", [edge])]
-    raise PrimitiveFinished(a)
+    yield [("RETURN", [a])]
 
 def dict_delete_node(a, b, **remainder):
-    edge, = yield [("RDNE", [a, b])]
+    edge, = yield [("RDNE", [a['id'], b['id']])]
     if edge is None:
         print("Failed dict_delete_node!")
     yield [("DE", [edge])]
-    raise PrimitiveFinished(a)
+    yield [("RETURN", [a])]
 
 def dict_read(a, b, **remainder):
-    b_value, = yield [("RV", [b])]
-    result, = yield [("RD", [a, b_value])]
-    raise PrimitiveFinished(result)
+    if "value" not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    result, = yield [("RD", [a['id'], b['value']])]
+    yield [("RETURN", [{'id': result}])]
 
 def dict_read_edge(a, b, **remainder):
-    b_value, = yield [("RV", [b])]
-    result, = yield [("RDE", [a, b_value])]
-    raise PrimitiveFinished(result)
+    if "value" not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    result, = yield [("RDE", [a['id'], b['value']])]
+    yield [("RETURN", [{'id': result}])]
 
 def dict_read_node(a, b, **remainder):
-    result, = yield [("RDN", [a, b])]
-    raise PrimitiveFinished(result)
+    result, = yield [("RDN", [a['id'], b['id']])]
+    yield [("RETURN", [{'id': result}])]
 
 def dict_in(a, b, **remainder):
-    b_value, = yield [("RV", [b])]
-    value, = yield [("RD", [a, b_value])]
-    is_in = value is not None
-    result, = yield [("CNV", [is_in])]
-    raise PrimitiveFinished(result)
+    if "value" not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    value, = yield [("RD", [a['id'], b['value']])]
+    yield [("RETURN", [{'value': value is not None}])]
 
 def dict_in_node(a, b, **remainder):
-    value, = yield [("RDN", [a, b])]
-    result, = yield [("CNV", [value is not None])]
-    raise PrimitiveFinished(result)
+    if "id" not in b:
+        # Not even allocated the node, so it is certain not to be in the dictionary
+        yield [("RETURN", [{'value': False}])]
+    value, = yield [("RDN", [a['id'], b['id']])]
+    yield [("RETURN", [{'value': value is not None}])]
 
 def dict_keys(a, **remainder):
-    keys, result = yield [("RDK", [a]), ("CN", [])]
+    keys, result = yield [("RDK", [a['id']]), ("CN", [])]
     edges = yield [("CE", [result, result]) for _ in keys]
     _ = yield [("CE", [edge, key]) for edge, key in zip(edges, keys)]
-    raise PrimitiveFinished(result)
+    yield [("RETURN", [{'id': result}])]
 
 def is_physical_int(a, **remainder):
-    t, = yield [("RV", [a])]
+    if "value" not in a:
+        a['value'], = yield [("RV", [a['id']])]
     try:
-        result, = yield [("CNV", [isinstance(t, int) or isinstance(t, long)])]
+        yield [("RETURN", [{'value': isinstance(a['value'], int) or isinstance(a['value'], long)}])]
     except NameError:
-        result, = yield [("CNV", [isinstance(t, int)])]
-
-    raise PrimitiveFinished(result)
+        yield [("RETURN", [{'value': isinstance(a['value'], int)}])]
 
 def is_physical_string(a, **remainder):
-    t, = yield [("RV", [a])]
+    if "value" not in a:
+        a['value'], = yield [("RV", [a['id']])]
     try:
-        result, = yield [("CNV", [isinstance(t, str) or isinstance(t, unicode)])]
+        yield [("RETURN", [{'value': isinstance(a['value'], str) or isinstance(a['value'], unicode)}])]
     except NameError:
-        result, = yield [("CNV", [isinstance(t, str)])]
-
-    raise PrimitiveFinished(result)
+        yield [("RETURN", [{'value': isinstance(a['value'], str)}])]
 
 def is_physical_float(a, **remainder):
-    t, = yield [("RV", [a])]
-    result, = yield [("CNV", [isinstance(t, float)])]
-    raise PrimitiveFinished(result)
+    if "value" not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    yield [("RETURN", [{'value': isinstance(a['value'], float)}])]
 
 def is_physical_boolean(a, **remainder):
-    t, = yield [("RV", [a])]
-    result, = yield [("CNV", [isinstance(t, bool)])]
-    raise PrimitiveFinished(result)
+    if "value" not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    yield [("RETURN", [{'value': isinstance(a['value'], bool)}])]
 
 def is_physical_action(a, **remainder):
-    t, = yield [("RV", [a])]
-    result, = yield [("CNV", [isinstance(t, dict) and t["value"] in ["if", "while", "assign", "call", "break", "continue", "return", "resolve", "access", "constant", "global", "declare"]])]
-    raise PrimitiveFinished(result)
+    if "value" not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    yield [("RETURN", [{'value': isinstance(a['value'], dict) and a['value']["value"] in ["if", "while", "assign", "call", "break", "continue", "return", "resolve", "access", "constant", "global", "declare"]}])]
 
 def is_physical_none(a, **remainder):
-    t, = yield [("RV", [a])]
-    result, = yield [("CNV", [isinstance(t, dict) and t["value"] == "none"])]
-    raise PrimitiveFinished(result)
+    if "value" not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    yield [("RETURN", [{'value': isinstance(a['value'], dict) and a['value']["value"] == "none"}])]
 
 def create_node(**remainder):
     result, = yield [("CN", [])]
-    raise PrimitiveFinished(result)
+    yield [("RETURN", [{'id': result}])]
 
 def create_edge(a, b, **remainder):
-    result, = yield [("CE", [a, b])]
-    raise PrimitiveFinished(result)
+    if "id" not in a:
+        #print("MATERIALIZING A create_edge")
+        a['id'], = yield [("CNV", [a['value']])]
+    if "id" not in b:
+        #print("MATERIALIZING B create_edge")
+        b['id'], = yield [("CNV", [b['value']])]
+    result, = yield [("CE", [a['id'], b['id']])]
+    yield [("RETURN", [{'id': result}])]
 
 def create_value(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [a_value])]
-    raise PrimitiveFinished(result)
+    if "value" not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    yield [("RETURN", [{'value': a['value']}])]
 
 def read_nr_out(a, **remainder):
-    outgoing, = yield [("RO", [a])]
-    result, = yield [("CNV", [len(outgoing)])]
-    raise PrimitiveFinished(result)
+    if "id" not in a:
+        yield [("RETURN", [{'value': 0}])]
+    else:
+        outgoing, = yield [("RO", [a['id']])]
+        yield [("RETURN", [{'value': len(outgoing)}])]
 
 def read_out(a, b, root, **remainder):
-    outgoing, b_value = yield [("RO", [a]), ("RV", [b])]
-    raise PrimitiveFinished(sorted(outgoing)[b_value] if len(outgoing) > b_value else root)
+    if "id" not in a:
+        a['id'], = yield [("CNV", [a['value']])]
+    if "value" not in b:
+        b['value'], = yield [("RV", [b['id']])]
+
+    outgoing, = yield [("RO", [a['id']])]
+    yield [("RETURN", [{'id': sorted(outgoing)[b['value']] if len(outgoing) > b['value'] else root}])]
 
 def read_nr_in(a, **remainder):
-    incoming, = yield [("RI", [a])]
-    result, = yield [("CNV", [len(incoming)])]
-    raise PrimitiveFinished(result)
+    if "id" not in a:
+        yield [("RETURN", [{'value': 0}])]
+    else:
+        incoming, = yield [("RI", [a['id']])]
+        yield [("RETURN", [{'value': len(incoming)}])]
 
 def read_in(a, b, root, **remainder):
-    incoming, b_value = yield [("RI", [a]), ("RV", [b])]
-    raise PrimitiveFinished(sorted(incoming)[b_value] if len(incoming) > b_value else root)
+    if "id" not in a:
+        a['id'], = yield [("CNV", [a['value']])]
+    if "value" not in b:
+        b['value'], = yield [("RV", [b['id']])]
+
+    incoming, = yield [("RI", [a['id']])]
+    yield [("RETURN", [{'id': sorted(incoming)[b['value']] if len(incoming) > b['value'] else root}])]
 
 def read_edge_src(a, **remainder):
-    result, = yield [("RE", [a])]
-    raise PrimitiveFinished(result[0])
+    result, = yield [("RE", [a['id']])]
+    yield [("RETURN", [{'id': result[0]}])]
 
 def read_edge_dst(a, **remainder):
-    result, = yield [("RE", [a])]
-    raise PrimitiveFinished(result[1])
+    result, = yield [("RE", [a['id']])]
+    yield [("RETURN", [{'id': result[1]}])]
 
 def delete_element(a, **remainder):
-    edge, = yield [("RE", [a])]
+    if "id" not in a:
+        yield [("RETURN", [{'value': False}])]
+
+    edge, = yield [("RE", [a['id']])]
     if edge[0] is None:
         # Not an edge:
-        yield [("DN", [a])]
-        result, = yield [("CNV", [False])]
-        raise PrimitiveFinished(result)
+        yield [("DN", [a['id']])]
+        yield [("RETURN", [{'value': False}])]
     else:
-        yield [("DE", [a])]
-        result, = yield [("CNV", [True])]
-        raise PrimitiveFinished(result)
+        yield [("DE", [a['id']])]
+        yield [("RETURN", [{'value': True}])]
 
 def read_root(root, **remainder):
-    raise PrimitiveFinished(root)
+    yield [("RETURN", [{'id': root}])]
 
 def is_edge(a, **remainder):
-    edge, = yield [("RE", [a])]
-    result, = yield [("CNV", [edge[0] is not None])]
-    raise PrimitiveFinished(result)
+    if "id" not in a:
+        yield [("RETURN", [{'value': False}])]
+
+    edge, = yield [("RE", [a['id']])]
+    yield [("RETURN", [{'value': edge[0] is not None}])]
 
 def log(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    print("== LOG == " + str(a_value))
-    raise PrimitiveFinished(a)
+    if "value" not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    print("== LOG == " + str(a['value']))
+    yield [("RETURN", [a])]
 
 def read_taskroot(task_root, **remainder):
-    raise PrimitiveFinished(task_root)
+    yield [("RETURN", [{'id': task_root}])]
 
 def time(**remainder):
-    a, = yield [("CNV", [python_time.time()])]
-    raise PrimitiveFinished(a)
+    yield [("RETURN", [{'value': python_time.time()}])]
 
 def hash(a, **remainder):
-    a_value, = yield [("RV", [a])]
+    if "value" not in a:
+        a['value'], = yield [("RV", [a['id']])]
     import hashlib
+
     try:
-        b_value = hashlib.sha512(a_value).hexdigest()
+        value = hashlib.sha512(a['value']).hexdigest()
     except TypeError:
-        b_value = hashlib.sha512(a_value.encode()).hexdigest()
-    b, = yield [("CNV", [b_value])]
-    raise PrimitiveFinished(b)
+        value = hashlib.sha512(a['value'].encode()).hexdigest()
+    yield [("RETURN", [{'value': value}])]
 
 def __sleep(a, b, **remainder):
-    timeout, interruptable = yield [("RV", [a]), ("RV", [b])]
+    if "value" not in a:
+        a['value'], = yield [("RV", [a['id']])]
+    if "value" not in b:
+        b['value'], = yield [("RV", [b['id']])]
+    timeout = a['value']
+    interruptable = b['value']
     yield [("SLEEP", [timeout, interruptable])]
-    raise PrimitiveFinished(a)
+    yield [("RETURN", [a])]
 
 def is_error(a, **remainder):
-    if a is None:
-        result, = yield [("CNV", [True])]
+    if a['id'] is None:
+        yield [("RETURN", [{'value': True}])]
     else:
-        result, = yield [("CNV", [False])]
-    raise PrimitiveFinished(result)
+        yield [("RETURN", [{'value': False}])]

+ 36 - 369
kernel/modelverse_kernel/request_handler.py

@@ -1,388 +1,55 @@
 import sys
 import modelverse_kernel.primitives as primitive_functions
-import modelverse_jit.runtime as jit_runtime
+import modelverse_kernel.jit as jit
 from collections import defaultdict
 
-class KnownRequestHandled(Exception):
-    """An exception that signifies that a known request was handled."""
-    pass
-
-def format_stack_trace(stack_trace):
-    """Formats a list of (function name, debug info, origin) triples."""
-    return '\n'.join([jit_runtime.format_stack_frame(*triple) for triple in stack_trace])
-
-class UnhandledRequestHandlerException(Exception):
-    """The type of exception that is thrown when the request handler encounters an
-       unhandled exception."""
-    def __init__(self, inner_exception, stack_trace):
-        import traceback
-        Exception.__init__(
-            self,
-            """The request handler encountered an unknown exception.\n
-               Inner exception: %s\n
-               Stack trace:\n%s\n""" % (traceback.format_exc(), format_stack_trace(stack_trace)))
-        self.inner_exception = inner_exception
-        self.stack_trace = stack_trace
-
 class RequestHandler(object):
-    """A type of object that intercepts logic-related Modelverse requests, and
-       forwards Modelverse state requests."""
     def __init__(self):
-        # generator_stack is a stack of GeneratorStackEntry values.
         self.generator_stack = []
-        # exception_handlers is a stack of
-        # (generator_stack index, [(exception type, handler function)])
-        # tuples.
-        self.exception_handlers = []
-        self.produce_stack_trace = True
-        self.handlers = {
-            'CALL' : self.execute_call,
-            'CALL_ARGS' : self.execute_call_args,
-            'CALL_KWARGS' : self.execute_call_kwargs,
-            'TAIL_CALL' : self.execute_tail_call,
-            'TAIL_CALL_ARGS' : self.execute_tail_call_args,
-            'TAIL_CALL_KWARGS' : self.execute_tail_call_kwargs,
-            'TRY' : self.execute_try,
-            'CATCH' : self.execute_catch,
-            'END_TRY' : self.execute_end_try,
-            'DEBUG_INFO' : self.execute_debug_info,
-            'SLEEP' : self.execute_sleep,
-        }
-
-    def is_active(self):
-        """Tests if this request handler has a top-of-stack generator."""
-        return len(self.generator_stack) > 0
-
-    def handle_request(self, reply):
-        """Replies to a request from the top-of-stack generator, and returns a new request."""
-        if not self.generator_stack:
-            raise ValueError('handle_request cannot be called with an empty generator stack.')
-
-        # Append the server's replies to the list of replies.
-        if reply is not None:
-            gen = self.generator_stack[-1]
-            if gen["replies"] is None:
-                gen["replies"] = reply
-            else:
-                gen["replies"].extend(reply)
-
-        while 1:
-            # Silence pylint's warning about catching Exception.
-            # pylint: disable=I0011,W0703
-            try:
-                gen = self.generator_stack[-1]
-                if gen["finished_requests"]:
-                    gen["pending_requests"] = gen["generator"].send(gen["replies"])
-                    gen["finished_requests"] = False
-                    gen["replies"] = None
-                return self.pop_requests()
-
-            except KnownRequestHandled:
-                pass
-            except StopIteration:
-                # Done, so remove the generator
-                self.pop_generator()
-                if self.generator_stack:
-                    # This generator was called from another generator.
-                    # Append 'None' to the caller's list of replies.
-                    self.append_reply(None)
-                else:
-                    # Looks like we're done here.
-                    return None
-            except primitive_functions.PrimitiveFinished as ex:
-                # Done, so remove the generator
-                self.pop_generator()
-                if self.generator_stack:
-                    # This generator was called from another generator.
-                    # Append the callee's result to the caller's list of replies.
-                    self.append_reply(ex.result)
-                else:
-                    # Looks like we're done here.
-                    return None
-            except primitive_functions.SleepKernel:
-                raise
-            except Exception as ex:
-                # Maybe get an exception handler to do this.
-                stack_trace = self.handle_exception(ex)
-                if stack_trace is not None:
-                    if self.produce_stack_trace:
-                        raise UnhandledRequestHandlerException(ex, stack_trace)
-                    else:
-                        raise
-
-    def set_finished_requests_flag(self):
-        """Sets the finished_requests flag in the top-of-stack tuple."""
-        self.generator_stack[-1]["finished_requests"] = True
+        self.handlers = {"CALL": self.execute_call,
+                         "CALL_ARGS": self.execute_call_args,
+                         "CALL_KWARGS": self.execute_call_kwargs,
+                         "RETURN": self.execute_return,
+                         "FINISH": self.execute_finish,
+                         "SLEEP": self.execute_sleep}
 
     def push_generator(self, gen):
-        """Pushes a new generator onto the stack."""
-        dd = defaultdict(lambda : None)
-        dd["generator"] = gen
-        dd["finished_requests"] = True
-        self.generator_stack.append(dd)
-        # print('Pushed generator %s. Generator count: %d' % (gen, len(self.generator_stack)))
-
-    def pop_generator(self):
-        """Removes the top-of-stack generator from the generator stack."""
-        # Pop the generator itself.
-        #self.generator_stack.pop()
-        del self.generator_stack[-1]
-        # print('Popped generator %s. Generator count: %d' % (gen, len(self.generator_stack)))
-        # Pop any exception handlers defined by the generator.
-        top_of_stack_index = len(self.generator_stack)
-        while self.exception_handlers:
-            if self.exception_handlers[-1][0] == top_of_stack_index:
-                # Pop exception handlers until exception_handlers is empty or until
-                # we find an exception handler that is not associated with the popped
-                # generator.
-                #self.exception_handlers.pop()
-                del self.exception_handlers[-1]
-            else:
-                # We're done here.
-                break
-
-    def append_reply(self, new_reply):
-        """Appends a reply to the top-of-stack generator's list of pending replies."""
-        if self.generator_stack[-1]["replies"] is None:
-            self.generator_stack[-1]["replies"] = [new_reply]
-        else:
-            self.generator_stack[-1]["replies"].append(new_reply)
-
-    def handle_exception(self, exception):
-        """Handles the given exception. A Boolean is returned that tells if
-           the exception was handled."""
-        # print('Exception thrown from %s: %s' % (str(self.generator_stack[-1]), str(exception)))
-        while self.exception_handlers:
-            # Pop the top-of-stack exception handler.
-            stack_index, handlers = self.exception_handlers.pop()
-
-            # Try to find an applicable handler.
-            applicable_handler = None
-            for handled_type, handler in handlers:
-                if isinstance(exception, handled_type):
-                    applicable_handler = handler
-
-            if applicable_handler is not None:
-                # We handle exceptions by first clearing the current stack frame and
-                # all of its children. Then, we place a dummy frame on the stack with
-                # a single 'TAIL_CALL_ARGS' request. The next iteration will replace
-                # the dummy frame by an actual frame.
-                del self.generator_stack[stack_index:]
-                stack_entry = defaultdict(lambda : None)
-                stack_entry["pending_requests"] = [('TAIL_CALL_ARGS', [applicable_handler, (exception,)])]
-                stack_entry["finished_requests"] = False
-                self.generator_stack.append(stack_entry)
-                return None
+        self.generator_stack.append(gen)
 
-        # We couldn't find an applicable exception handler, even after exhausting the
-        # entire exception handler stack. All is lost.
-        # Also, clean up after ourselves by unwinding the stack.
-        return self.unwind_stack()
-
-    def unwind_stack(self):
-        """Unwinds the entirety of the stack. All generators and exception handlers are
-           discarded. A list of (function name, debug information, source) statements is
-           returned."""
-        class UnwindStackException(Exception):
-            """A hard-to-catch exception that is used to make generators crash.
-               The exceptions they produce can then be analyzed for line numbers."""
-            pass
-
-        # First throw away all exception handlers. We won't be needing them any more.
-        self.exception_handlers = []
-
-        # Then pop every generator from the stack and make it crash.
-        stack_trace = []
+    def handle_request(self, reply):
+        self.reply = reply
         while self.generator_stack:
-            top_entry = self.generator_stack.pop()
-            if top_entry["function_origin"] is None:
-                # Skip this function.
-                continue
-
-            try:
-                # Crash the generator.
-                top_entry["generator"].throw(UnwindStackException())
-            except UnwindStackException:
-                # Find out where the exception was thrown.
-                _, _, exc_traceback = sys.exc_info()
-                line_number = exc_traceback.tb_lineno
-                source_map = top_entry["source_map"]
-                if source_map is not None:
-                    debug_info = source_map.get_debug_info(line_number)
-                else:
-                    debug_info = None
-
-                function_name = top_entry["function_name"]
-                stack_trace.append((function_name, debug_info, top_entry["function_origin"]))
+            requests = self.generator_stack[-1].send(self.reply)
 
-        return stack_trace[::-1]
-
-    def pop_requests(self):
-        """Tries to pop a batch of Modelverse _state_ requests from the
-           current list of requests. Known requests are executed immediately.
-
-           A list of requests and a Boolean are returned. The latter is True
-           if there are no more requests to process, and false otherwise."""
-        requests = self.generator_stack[-1]["pending_requests"]
-        if requests:
-            if requests[0][0] in self.handlers:
-                # First element is a known request
-                #elem = requests.pop(0)
-                elem = requests[0]
-                del requests[0]
-
-                # The list of requests might be empty now. If so, then flag this
-                # batch of requests as finished.
-                if not requests:
-                    self.set_finished_requests_flag()
-
-                # Handle the request.
-                self.handlers[elem[0]](elem[1])
-                raise KnownRequestHandled()
+            # Generated new request, so process
+            if requests and requests[0][0] in self.handlers:
+                # This next command potentially raises a finished message already, meaning that we should stop already
+                # We avoid an extra try/except block by putting the None on the stack already
+                self.handlers[requests[0][0]](requests[0][1])
             else:
-                for i, elem in enumerate(requests):
-                    if elem[0] in self.handlers:
-                        # Handle any requests that precede the known request first.
-                        pre_requests = requests[:i]
-                        del requests[:i]
-                        return pre_requests
+                # MvS request, so forward that instead
+                return requests
+                
+    def execute_finish(self, request_args):
+        self.generator_stack = []
+        
+    def execute_sleep(self, request_args):
+        raise primitive_functions.SleepKernel(request_args[0], request_args[1])
 
-        # We couldn't find a known request in the batch of requests, so we might as well
-        # handle them all at once then.
-        self.set_finished_requests_flag()
-        return requests
+    def execute_return(self, request_args):
+        del self.generator_stack[-1]
+        self.reply = [request_args[0]]
 
     def execute_call(self, request_args):
-        """Executes a CALL-request with the given argument list."""
-        # Format: ("CALL", [gen])
-        gen, = request_args
-        self.push_generator(gen)
-
-    def execute_call_kwargs(self, request_args):
-        """Executes a CALL_KWARGS-request with the given argument list."""
-        # Format: ("CALL_KWARGS", [func, kwargs])
-        # This format is useful because it also works for functions that
-        # throw an exception but never yield.
-        func, kwargs = request_args
-        # We need to be extra careful here, because func(**kwargs) might
-        # not be a generator at all: it might simply be a method that
-        # raises an exception. To cope with this we need to push a dummy
-        # entry onto the stack if a StopIteration or PrimtiveFinished
-        # exception is thrown. The logic in execute_yields will then pop
-        # that dummy entry.
-        try:
-            self.push_generator(func(**kwargs))
-        except StopIteration:
-            self.push_generator(None)
-            raise
-        except primitive_functions.PrimitiveFinished:
-            self.push_generator(None)
-            raise
-        except:
-            print("EXCEPTION for " + str(locals()))
-            raise
+        self.generator_stack.append(request_args[0])
+        self.reply = None
 
     def execute_call_args(self, request_args):
-        """Executes a CALL_ARGS-request with the given argument list."""
-        # Format: ("CALL_ARGS", [gen, args])
-        func, args = request_args
-        # We need to be extra careful here, because func(*args) might
-        # not be a generator at all: it might simply be a method that
-        # raises an exception. To cope with this we need to push a dummy
-        # entry onto the stack if a StopIteration or PrimtiveFinished
-        # exception is thrown. The logic in execute_yields will then pop
-        # that dummy entry.
-        try:
-            self.push_generator(func(*args))
-        except StopIteration:
-            self.push_generator(None)
-            raise
-        except primitive_functions.PrimitiveFinished:
-            self.push_generator(None)
-            raise
-
-    def execute_tail_call(self, request_args):
-        """Executes a TAIL_CALL-request with the given argument list."""
-        # Format: ("TAIL_CALL", [gen])
-        self.pop_generator()
-        self.execute_call(request_args)
-
-    def execute_tail_call_args(self, request_args):
-        """Executes a TAIL_CALL_ARGS-request with the given argument list."""
-        # Format: ("TAIL_CALL_ARGS", [gen, args])
-        self.pop_generator()
-        self.execute_call_args(request_args)
+        #print("CALL " + str(request_args[0]))
+        self.generator_stack.append(request_args[0](*(request_args[1])))
+        self.reply = None
 
-    def execute_tail_call_kwargs(self, request_args):
-        """Executes a TAIL_CALL_KWARGS-request with the given argument list."""
-        # Format: ("TAIL_CALL_KWARGS", [gen, kwargs])
-        self.pop_generator()
-        self.execute_call_kwargs(request_args)
-
-    def execute_try(self, request_args):
-        """Executes a TRY-request with the given argument list."""
-        # TRY pushes an exception handler onto the exception handler stack.
-        # Format: ("TRY", [])
-        if len(request_args) != 0:
-            raise ValueError(
-                ("TRY was given argument list '%s', " +
-                 "expected exactly zero arguments.") % repr(request_args))
-        self.exception_handlers.append((len(self.generator_stack) - 1, []))
-        self.append_reply(None)
-
-    def execute_catch(self, request_args):
-        """Executes a CATCH-request with the given argument list."""
-        if len(request_args) != 2:
-            raise ValueError(
-                ("CATCH was given argument list '%s', "
-                 "expected exactly two arguments: an exception "
-                 "type and an exception handler.") % repr(request_args))
-        exception_type, handler = request_args
-        stack_index, handlers = self.exception_handlers[-1]
-        if stack_index != len(self.generator_stack) - 1:
-            raise ValueError(
-                'Cannot comply with CATCH because there is no exception handler for the '
-                'current generator.')
-
-        handlers.append((exception_type, handler))
-        self.append_reply(None)
-
-    def execute_end_try(self, request_args):
-        """Executes an END_TRY-request with the given argument list."""
-        # END_TRY pops a value from the exception handler stack. The
-        # popped value must reference the top-of-stack element in the
-        # generator stack. END_TRY takes no arguments.
-        # Format: ("END_TRY", [])
-        if len(request_args) != 0:
-            raise ValueError(
-                "END_TRY was given argument list '%s', expected '%s'." % (
-                    repr(request_args), repr([])))
-
-        if len(self.exception_handlers) == 0:
-            raise ValueError(
-                'Cannot comply with END_TRY because the exception handler stack is empty.')
-
-        stack_index, _ = self.exception_handlers[-1]
-        if stack_index != len(self.generator_stack) - 1:
-            raise ValueError(
-                'Cannot comply with END_TRY because there is no exception handler for the '
-                'current generator.')
-
-        # Everything seems to be in order. Pop the exception handler.
-        self.exception_handlers.pop()
-        self.append_reply(None)
-
-    def execute_debug_info(self, request_args):
-        """Executes a DEBUG_INFO-request with the given argument list."""
-        # DEBUG_INFO updates the function name and source map for the top-of-stack generator.
-        # These two things allow us to unwind the stack neatly if an unhandled exception is
-        # encountered.
-        # Format: ("DEBUG_INFO", [function_name, source_map])
-        top_entry = self.generator_stack[-1]
-        top_entry["function_name"], top_entry["source_map"], top_entry["function_origin"] = request_args
-        self.append_reply(None)
-
-    def execute_sleep(self, request_args):
-        """Executes a SLEEP-request with the given argument list."""
-        self.append_reply(None)
-        raise primitive_functions.SleepKernel(request_args[0], request_args[1])
+    def execute_call_kwargs(self, request_args):
+        #print("KWCALL " + str(request_args[0]))
+        self.generator_stack.append(request_args[0](**(request_args[1])))
+        self.reply = None

+ 0 - 17
kernel/mvk_server/python_runtime/.project

@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>python_runtime</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.python.pydev.PyDevBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.python.pydev.pythonNature</nature>
-	</natures>
-</projectDescription>

+ 0 - 5
kernel/mvk_server/python_runtime/.pydevproject

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?eclipse-pydev version="1.0"?><pydev_project>
-<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
-<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
-</pydev_project>

+ 0 - 0
kernel/mvk_server/python_runtime/__init__.py


+ 0 - 9
kernel/mvk_server/python_runtime/accurate_time.py

@@ -1,9 +0,0 @@
-import time as t
-import os
-
-if os.name == 'posix':
-	def time():
-		return t.time()
-elif os.name == 'nt':
-	def time():
-		return t.clock()

+ 0 - 58
kernel/mvk_server/python_runtime/event_queue.py

@@ -1,58 +0,0 @@
-from kernel.mvk_server.python_runtime.infinity import INFINITY
-
-class EventQueue(object):
-    class EventQueueEntry(object):        
-        def __init__(self, event_list, time_offset) :
-            self.event_list = event_list
-            self.time_offset = time_offset
-        
-        def decreaseTime(self, offset) :
-            self.time_offset -= offset;   
-        
-        def getEvents(self) :
-            return self.event_list
-        
-        def getTime (self) :
-            return self.time_offset
-
-    def __init__(self):
-        self.event_list = []
-
-    def add(self, event_list, time_offset) :
-        entry = EventQueue.EventQueueEntry(event_list, time_offset);
-        #We maintain a sorted stable list
-        insert_index = 0;
-        index = len(self.event_list)-1
-        while (index >= 0) :
-            if (self.event_list[index].getTime() <= time_offset) :
-                insert_index = index + 1;
-                break;
-            index -= 1
-        self.event_list.insert(insert_index, entry)
-    
-    def decreaseTime(self, offset) :
-        for event in self.event_list :
-            event.decreaseTime(offset)
-    
-    def isEmpty(self) :
-        return len(self.event_list) == 0
-    
-    def getEarliestTime(self) :
-        """Returns the earliest time. INFINITY if no events are present."""
-        if self.isEmpty() :
-            return INFINITY
-        else :
-            return self.event_list[0].getTime()
-    
-    def popDueEvents(self) :
-        result = []
-        if (self.isEmpty() or self.event_list[0].getTime() > 0.0) :
-            #There are no events, or the earliest event isn't due, so we can already return an emtpy result
-            return result
-
-        index = 0;
-        while (index < len(self.event_list) and self.event_list[index].getTime() <= 0.0) :
-            result.append(self.event_list[index].getEvents()) #Add all events that are due (offset less than 0) to the result
-            index += 1
-        self.event_list = self.event_list[len(result):]
-        return result;

+ 0 - 3
kernel/mvk_server/python_runtime/infinity.py

@@ -1,3 +0,0 @@
-# Instantiate singleton:        
-INFINITY = float('inf')
-

+ 0 - 1
kernel/mvk_server/python_runtime/libs/__init__.py

@@ -1 +0,0 @@
-

+ 0 - 59
kernel/mvk_server/python_runtime/libs/drawing.py

@@ -1,59 +0,0 @@
-"""
- *REALLY* Small framework for creating/manipulating/deleting Tkinter Canvas elements.
- 
- NOTE: keep this synced with svg.js
- 
- Author: Raphael Mannadiar
- Date: 2014/08/21
-"""
-
-from kernel.mvk_server.python_runtime.libs.utils import utils
-
-
-class drawing:
-    class canvas_wrapper:
-        def __init__(self, element):
-            self.element = element
-            self.width = int(element.cget("width"))
-            self.height = int(element.cget("height"))
-
-        def add_circle(self, x, y, r, style):
-            new_element_id = self.element.create_oval(x-r, y-r, x+r, y+r, **style)
-            return drawing.ui_element_wrapper(self, new_element_id, x, y)
-
-        def add_rectangle(self, x, y, w, h, style):
-            new_element_id = self.element.create_rectangle(x-w/2.0, y-h/2.0, x+w/2.0, y+h/2.0, **style)
-            return drawing.ui_element_wrapper(self, new_element_id, x, y)
-
-        def remove_element(self, element):
-            self.element.delete(element.element_id)
-
-
-    class ui_element_wrapper:
-        def __init__(self, canvas_wrapper, element_id, x, y):
-            self.canvas_wrapper = canvas_wrapper
-            self.element_id = element_id
-            self.a = 0
-            self.x = x
-            self.y = y
-
-        def set_position(self, x, y):
-            self.move(x-self.x, y-self.y)
-
-        def get_position(self):
-            return utils._bunch(x=self.x, y=self.y)
-
-        def move(self, dx, dy):
-            self.x += dx
-            self.y += dy
-            self.canvas_wrapper.element.move(self.element_id, dx, dy)
-
-        def set_rotation(self, a):
-            raise Exception("Not implemented yet")
-
-        def rotate(self, a):
-            raise Exception("Not implemented yet")
-
-        def set_color(self, color):
-            self.canvas_wrapper.element.itemconfig(self.element_id, fill=color)
-

+ 0 - 111
kernel/mvk_server/python_runtime/libs/ui.py

@@ -1,111 +0,0 @@
-"""
- *REALLY* Small framework for creating/manipulating/deleting gui elements in Tkinter.
- 
- NOTE: keep this synced with ui.js
- 
- Author: Raphael Mannadiar
- Date: 2014/08/21
-"""
-
-try:
-	import Tkinter as tk
-except ImportError:
-	import tkinter as tk
-
-from kernel.mvk_server.python_runtime.statecharts_core import Event
-from kernel.mvk_server.python_runtime.libs.drawing import drawing
-from kernel.mvk_server.python_runtime.libs.utils import utils
-
-
-class ui:
-	window = None
-	__nextWindowId = 0
-
-	EVENTS = utils._bunch(
-		KEY_PRESS = 			'<Key>',
-		MOUSE_CLICK = 			'<Button>',
-		MOUSE_MOVE = 			'<Motion>',
-		MOUSE_PRESS =			'<ButtonPress>',
-		MOUSE_RELEASE =		'<ButtonRelease>',
-		MOUSE_RIGHT_CLICK =	'<Button-3>',
-		WINDOW_CLOSE = 		'WM_DELETE_WINDOW');
-
-	MOUSE_BUTTONS = utils._bunch(
-		LEFT		= 1,
-		MIDDLE	= 2,
-		RIGHT		= 3);
-
-	KEYCODES	= utils._bunch(
-		DELETE	= 46);
-
-	@staticmethod
-	def append_button(_window,text):
-		button = tk.Button(_window, text=text)
-		button.pack()
-		return ui.wrap_element(button)
-
-
-	@staticmethod
-	def append_canvas(_window,width,height,style):
-		canvas = tk.Canvas(_window,width=width,height=height)
-		canvas.config(**style)
-		canvas.pack()
-		return drawing.canvas_wrapper(canvas)
-
-
-	@staticmethod
-	def bind_event(source,event,controller,raise_name,port="ui",time_offset=0.0):
-
-		def __handle_event(ev=None):
-			if event == ui.EVENTS.KEY_PRESS :
-				controller.addInput(Event(raise_name, port, [ev.keycode,source]),time_offset)
-
-			elif event == ui.EVENTS.MOUSE_CLICK or \
-				  event == ui.EVENTS.MOUSE_MOVE or \
-				  event == ui.EVENTS.MOUSE_PRESS or \
-				  event == ui.EVENTS.MOUSE_RELEASE or \
-		  		  event == ui.EVENTS.MOUSE_RIGHT_CLICK :
-				controller.addInput(Event(raise_name, port, [ev.x, ev.y, ev.num]),time_offset)
-
-			elif event == ui.EVENTS.WINDOW_CLOSE :
-				controller.addInput(Event(raise_name, port, [source]),time_offset)
-
-			else :
-				raise Exception('Unsupported event');
-	
-		if event == ui.EVENTS.WINDOW_CLOSE :
-			source.protocol(event, __handle_event)
-
-		elif issubclass(drawing.ui_element_wrapper,source.__class__) :
-			source.canvas_wrapper.element.tag_bind(source.element_id, event, __handle_event)
-
-		else :
-			source.bind(event, __handle_event)
-
-
-	@staticmethod
-	def close_window(_window):
-		_window.destroy()
-
-
-	@staticmethod
-	def log(value):
-		print(value)
-
-
-	@staticmethod
-	def new_window(width,height):
-		_window = tk.Toplevel(ui.window)
-		_window.geometry(str(width)+"x"+str(height)+"+300+300")
-		return _window
-
-
-	@staticmethod
-	def println(value,target):
-		raise Exception('Not implemented yet');
-
-
-	@staticmethod
-	def wrap_element(element):
-		return utils._bunch(element=element)
-

+ 0 - 19
kernel/mvk_server/python_runtime/libs/utils.py

@@ -1,19 +0,0 @@
-import random
-
-class utils:
-
-	@staticmethod
-	def random():
-		return random.random()
-
-
-	"""
-		provide "." access to dictionaries
-
-		example: d = {'a':1}
-			before: d['a'] => 1, d.a => error
-			after:  d['a'] = d.a
-	"""
-	class _bunch:
-		def __init__(self, **kwds):
-			self.__dict__.update(kwds)

+ 0 - 22
kernel/mvk_server/python_runtime/nextafter.py

@@ -1,22 +0,0 @@
-import imp
-
-try:
-	# if module 'numpy' exists, use it
-	found = imp.find_module('numpy')
-	nextafter = imp.load_module('numpy', *found).nextafter
-
-except ImportError:
-	import math
-	# this ad-hoc implementation won't always give the exact same result as the C implementation used by numpy, but it's good enough for our purposes
-	def nextafter(x, y):
-		m,e = math.frexp(x)
-		exp = e - 53
-		if exp < -1022 or m == 0.0:
-			exp = -1022
-		epsilon = math.ldexp(1.0, exp)
-		if y > x:
-			return x + epsilon
-		elif y < x:
-			return x - epsilon
-		else:
-			return x

+ 0 - 945
kernel/mvk_server/python_runtime/statecharts_core.py

@@ -1,945 +0,0 @@
-import abc
-import re
-from kernel.mvk_server.python_runtime.accurate_time import time
-import threading
-import traceback
-import math
-from kernel.mvk_server.python_runtime.nextafter import nextafter
-from kernel.mvk_server.python_runtime.infinity import INFINITY
-from kernel.mvk_server.python_runtime.event_queue import EventQueue
-
-try:
-	from Queue import Queue, Empty
-except ImportError:
-	from queue import Queue, Empty
-
-class RuntimeException(Exception):
-	def __init__(self, message):
-		self.message = message
-	def __str__(self):
-		return repr(self.message)
-
-class AssociationException(RuntimeException):
-	pass
-
-class AssociationReferenceException(RuntimeException):
-	pass
-
-class ParameterException(RuntimeException):
-	pass
-
-class InputException(RuntimeException):
-	pass
-
-class Association(object):
-	#wrapper object for one association relation
-	def __init__(self, to_class, min_card, max_card):
-		self.to_class = to_class
-		self.min_card = min_card
-		self.max_card = max_card
-		self.instances = {}  # maps index (as string) to instance
-		self.instances_to_ids = {}
-		self.size = 0
-		self.next_id = 0
-		
-
-	def allowedToAdd(self):
-		return self.max_card == -1 or self.size < self.max_card
-		
-	def allowedToRemove(self):
-		return self.min_card == -1 or self.size > self.min_card
-		
-	def addInstance(self, instance):
-		if self.allowedToAdd() :
-			new_id = self.next_id
-			self.next_id += 1
-			self.instances[new_id] = instance
-			self.instances_to_ids[instance] = new_id
-			self.size += 1
-			return new_id
-		else :
-			raise AssociationException("Not allowed to add the instance to the association.")
-		
-	def removeInstance(self, instance):
-		if self.allowedToRemove() :
-			del self.instances[self.instances_to_ids[instance]]
-			del self.instances_to_ids[instance]
-			self.size -= 1
-		else :
-			raise AssociationException("Not allowed to remove the instance from the association.")
-		
-	def getInstance(self, index):
-		try :
-			return self.instances[index]
-		except IndexError :
-			raise AssociationException("Invalid index for fetching instance(s) from association.")
-
-"""class InstanceWrapper(object):
-	#wrapper object for an instance and its relevant information needed in the object manager
-	def __init__(self, instance, associations):
-		self.instance = instance
-		self.associations = {}
-		for association in associations :
-			self.associations[association.getName()] = association  
-		
-	def getAssociation(self, name):
-		try :
-			return self.associations[name]
-		except KeyError :
-			raise AssociationReferenceException("Unknown association %s." % name)
-	
-	def getInstance(self):
-		return self.instance"""
-
-class ObjectManagerBase(object):
-	__metaclass__  = abc.ABCMeta
-	
-	def __init__(self, controller):
-		self.controller = controller
-		self.events = EventQueue()
-		self.instances = set() #a dictionary that maps RuntimeClassBase to InstanceWrapper
-		
-	def addEvent(self, event, time_offset = 0.0):
-		self.events.add(event, time_offset)
-		
-	# Broadcast an event to all instances
-	def broadcast(self, new_event):
-		for i in self.instances:
-			i.addEvent(new_event)
-		
-	def getWaitTime(self):  
-		#first get waiting time of the object manager's events
-		smallest_time = self.events.getEarliestTime()
-		#check all the instances
-		for instance in self.instances:
-			smallest_time = min(smallest_time, instance.getEarliestEventTime())
-		return smallest_time
-	
-	def stepAll(self, delta):
-		self.step(delta)
-		for i in self.instances:
-			i.step(delta)
-
-	def step(self, delta):
-		self.events.decreaseTime(delta)
-		for event in self.events.popDueEvents() :
-			self.handleEvent(event)
-			   
-	def start(self):
-		for i in self.instances:
-			i.start()		  
-			   
-	def handleEvent(self, e):   
-		if e.getName() == "narrow_cast" :
-			self.handleNarrowCastEvent(e.getParameters())
-			
-		elif e.getName() == "broad_cast" :
-			self.handleBroadCastEvent(e.getParameters())
-			
-		elif e.getName() == "create_instance" :
-			self.handleCreateEvent(e.getParameters())
-			
-		elif e.getName() == "associate_instance" :
-			self.handleAssociateEvent(e.getParameters())
-			
-		elif e.getName() == "start_instance" :
-			self.handleStartInstanceEvent(e.getParameters())
-			
-		elif e.getName() == "delete_instance" :
-			self.handleDeleteInstanceEvent(e.getParameters())
-			
-	def processAssociationReference(self, input_string):
-		if len(input_string) == 0 :
-			raise AssociationReferenceException("Empty association reference.")
-		regex_pattern = re.compile("^([a-zA-Z_]\w*)(?:\[(\d+)\])?$")
-		path_string =  input_string.split("/")
-		result = []
-		for piece in path_string :
-			match = regex_pattern.match(piece)
-			if match :
-				name = match.group(1)
-				index = match.group(2)
-				if index is None :
-					index = -1
-				result.append((name,int(index)))
-			else :
-				raise AssociationReferenceException("Invalid entry in association reference. Input string: " + input_string)
-		return result
-	
-	def handleStartInstanceEvent(self, parameters):
-		if len(parameters) != 2 :
-			raise ParameterException ("The start instance event needs 2 parameters.")  
-		else :
-			source = parameters[0]
-			traversal_list = self.processAssociationReference(parameters[1])
-			for i in self.getInstances(source, traversal_list) :
-				i["instance"].start()
-			source.addEvent(Event("instance_started", parameters = [parameters[1]]))
-		
-	def handleBroadCastEvent(self, parameters):
-		if len(parameters) != 1 :
-			raise ParameterException ("The broadcast event needs 1 parameter.")
-		self.broadcast(parameters[0])
-
-	def handleCreateEvent(self, parameters):
-		if len(parameters) < 2 :
-			raise ParameterException ("The create event needs at least 2 parameters.")
-
-		source = parameters[0]
-		association_name = parameters[1]
-		
-		association = source.associations[association_name]
-		#association = self.instances_map[source].getAssociation(association_name)
-		if association.allowedToAdd() :
-			''' allow subclasses to be instantiated '''
-			class_name = association.to_class if len(parameters) == 2 else parameters[2]
-			new_instance = self.createInstance(class_name, parameters[3:])
-			if not new_instance:
-				raise ParameterException("Creating instance: no such class: " + class_name)
-			#index = association.addInstance(new_instance)
-			try:
-				index = association.addInstance(new_instance)
-			except AssociationException as exception:
-				raise RuntimeException("Error adding instance to association '" + association_name + "': " + str(exception))
-			p = new_instance.associations.get("parent")
-			if p:
-				p.addInstance(source)
-			source.addEvent(Event("instance_created", None, [association_name+"["+str(index)+"]"]))
-		else :
-			source.addEvent(Event("instance_creation_error", None, [association_name]))
-
-	def handleDeleteInstanceEvent(self, parameters):
-		if len(parameters) < 2 :
-			raise ParameterException ("The delete event needs at least 2 parameters.")
-		else :
-			source = parameters[0]
-			association_name = parameters[1]
-			traversal_list = self.processAssociationReference(association_name)
-			instances = self.getInstances(source, traversal_list)
-			#association = self.instances_map[source].getAssociation(traversal_list[0][0])
-			association = source.associations[traversal_list[0][0]]
-			for i in instances:
-				try:
-					association.removeInstance(i["instance"])
-					self.instances.discard(i["instance"])
-				except AssociationException as exception:
-					raise RuntimeException("Error removing instance from association '" + association_name + "': " + str(exception))
-				i["instance"].stop()
-				#if hasattr(i.instance, 'user_defined_destructor'):
-				i["instance"].user_defined_destructor()
-			source.addEvent(Event("instance_deleted", parameters = [parameters[1]]))
-				
-	def handleAssociateEvent(self, parameters):
-		if len(parameters) != 3 :
-			raise ParameterException ("The associate_instance event needs 3 parameters.")
-		else :
-			source = parameters[0]
-			to_copy_list = self.getInstances(source,self.processAssociationReference(parameters[1]))
-			if len(to_copy_list) != 1 :
-				raise AssociationReferenceException ("Invalid source association reference.")
-			wrapped_to_copy_instance = to_copy_list[0]["instance"]
-			dest_list = self.processAssociationReference(parameters[2])
-			if len(dest_list) == 0 :
-				raise AssociationReferenceException ("Invalid destination association reference.")
-			last = dest_list.pop()
-			if last[1] != -1 :
-				raise AssociationReferenceException ("Last association name in association reference should not be accompanied by an index.")
-				
-			for i in self.getInstances(source, dest_list) :
-				i["instance"].associations[last[0]].addInstance(wrapped_to_copy_instance)
-		
-	def handleNarrowCastEvent(self, parameters):
-		if len(parameters) != 3 :
-			raise ParameterException ("The associate_instance event needs 3 parameters.")
-		source = parameters[0]
-		traversal_list = self.processAssociationReference(parameters[1])
-		cast_event = parameters[2]
-		for i in self.getInstances(source, traversal_list) :
-			i["instance"].addEvent(cast_event)
-		
-	def getInstances(self, source, traversal_list):
-		currents = [{
-			"instance" : source,
-			"ref" : None,
-			"assoc_name" : None,
-			"assoc_index" : None
-		}]
-		#currents = [source]
-		for (name, index) in traversal_list :
-			nexts = []
-			for current in currents :
-				association = current["instance"].associations[name]
-				if (index >= 0 ) :
-					nexts.append({
-						"instance" : association.instances[index],
-						"ref" : current["instance"],
-						"assoc_name" : name,
-						"assoc_index" : index
-					})
-				elif (index == -1) :
-					for i in association.instances:
-						nexts.append({
-							"instance" : association.instances[i],
-							"ref" : current["instance"],
-							"assoc_name" : name,
-							"assoc_index" : index
-						})
-					#nexts.extend( association.instances.values() )
-				else :
-					raise AssociationReferenceException("Incorrect index in association reference.")
-			currents = nexts
-		return currents
-			
-	@abc.abstractmethod
-	def instantiate(self, class_name, construct_params):
-		pass
-		
-	def createInstance(self, to_class, construct_params = []):
-		instance = self.instantiate(to_class, construct_params)
-		self.instances.add(instance)
-		return instance
-	
-class Event(object):
-	def __init__(self, event_name, port = "", parameters = []):
-		self.name = event_name
-		self.parameters = parameters
-		self.port = port
-
-	def getName(self):
-		return self.name
-
-	def getPort(self):
-		return self.port
-
-	def getParameters(self):
-		return self.parameters
-	
-	def __repr__(self):
-		representation = "(event name : " + str(self.name) + "; port : " + str(self.port)
-		if self.parameters :
-			representation += "; parameters : " + str(self.parameters)
-		representation += ")"
-		return representation
-	
-class OutputListener(object):
-	def __init__(self, port_names):
-		self.port_names = port_names
-		self.queue = Queue()
-
-	def add(self, event):
-		if len(self.port_names) == 0 or event.getPort() in self.port_names :
-			self.queue.put_nowait(event)
-			
-	""" Tries for timeout seconds to fetch an event, returns None if failed.
-		0 as timeout means no waiting (blocking), returns None if queue is empty.
-		-1 as timeout means blocking until an event can be fetched. """
-	def fetch(self, timeout = 0):
-		if timeout < 0:
-			timeout = INFINITY
-		while timeout >= 0:
-			try:
-				# wait in chunks of 100ms because we
-				# can't receive (keyboard)interrupts while waiting
-				return self.queue.get(True, 0.1 if timeout > 0.1 else timeout)
-			except Empty:
-				timeout -= 0.1
-		return None
-
-class InputPortEntry(object):
-	def __init__(self, virtual_name, instance):
-		self.virtual_name = virtual_name
-		self.instance = instance
-		
-class ControllerBase(object):
-
-	def __init__(self, object_manager):
-		self.object_manager = object_manager
-
-		self.private_port_counter = 0
-
-		# Keep track of input ports
-		self.input_ports = {}
-		self.input_queue = EventQueue()
-
-		# Keep track of output ports
-		self.output_ports = []
-		self.output_listeners = []
-
-		# Let statechart run one last time before stopping
-		self.done = False
-			
-	def addInputPort(self, virtual_name, instance = None):
-		if instance == None :
-			port_name = virtual_name
-		else:
-			port_name = "private_" + str(self.private_port_counter) + "_" + virtual_name
-			self.private_port_counter += 1
-		self.input_ports[port_name] = InputPortEntry(virtual_name, instance)
-		return port_name
-		
-	def addOutputPort(self, port_name):
-		self.output_ports.append(port_name)
-
-	def broadcast(self, new_event):
-		self.object_manager.broadcast(new_event)
-		
-	def start(self):
-		self.object_manager.start()
-	
-	def stop(self):
-		pass
-
-	def addInput(self, input_event_list, time_offset = 0.0):
-		if not isinstance(input_event_list, list):
-			input_event_list = [input_event_list]
-
-		for e in input_event_list:
-			if e.getName() == ""  :
-				raise InputException("Input event can't have an empty name.")
-		
-			if e.getPort() not in self.input_ports :
-				raise InputException("Input port mismatch, no such port: " + e.getPort() + ".")	 
-
-		self.input_queue.add(input_event_list, time_offset)
-
-	def getWaitTime(self):
-		return min(self.object_manager.getWaitTime(), self.input_queue.getEarliestTime())
-
-	def handleInput(self, delta):
-		self.input_queue.decreaseTime(delta)
-		for events in self.input_queue.popDueEvents():
-			for e in events:
-				input_port = self.input_ports[e.getPort()]
-				e.port = input_port.virtual_name
-				target_instance = input_port.instance
-				if target_instance == None:
-					self.broadcast(e)
-				else:
-					target_instance.addEvent(e)
-
-	def outputEvent(self, event):
-		for listener in self.output_listeners :
-			listener.add(event)
-
-	def addOutputListener(self, ports):
-		listener = OutputListener(ports)
-		self.output_listeners.append(listener)
-		return listener
-
-	def addMyOwnOutputListener(self, listener):
-		self.output_listeners.append(listener)
-
-	# deprecated, to add multiple events, use addInput instead
-	def addEventList(self, event_list):
-		for (event, time_offset) in event_list :
-			self.addInput(event, time_offset)
-			
-	def getObjectManager(self):
-		return self.object_manager
-		
-class GameLoopControllerBase(ControllerBase):
-	def __init__(self, object_manager):
-		ControllerBase.__init__(self, object_manager)
-		
-	def update(self, delta):
-		self.handleInput(delta)
-		self.object_manager.stepAll(delta)
-
-class EventLoop:
-	# parameters:
-	#  schedule - a callback scheduling another callback in the event loop
-	#      this callback should take 2 parameters: (callback, timeout) and return an ID
-	#  clear - a callback that clears a scheduled callback
-	#      this callback should take an ID that was returned by 'schedule'
-	def __init__(self, schedule, clear):
-		self.schedule_callback = schedule
-		self.clear_callback = clear
-		self.scheduled_id = None
-		self.last_time = None
-		self.next_wakeup = None
-		self.last_print = 0.0
-
-	def getScheduledTimeout(self):
-		if self.last_time and self.next_wakeup:
-			return self.next_wakeup - self.last_time
-		else:
-			return INFINITY
-
-	# schedule relative to last_time
-	#
-	# argument 'wait_time' is the amount of virtual (simulated) time to wait
-	#
-	# NOTE: if the next wakeup (in simulated time) is in the past, the timeout is '0',
-	# but because scheduling '0' timeouts hurts performance, we don't schedule anything
-	# and return False instead
-	def schedule(self, f, wait_time):
-		if self.scheduled_id:
-			# if the following error occurs, it is probably due to a flaw in the logic of EventLoopControllerBase
-			raise RuntimeException("EventLoop class intended to maintain at most 1 scheduled callback.")
-
-		if wait_time == INFINITY:
-			self.last_time = None
-			self.next_wakeup = None
-			is_scheduled = True
-		else:
-			now = time()
-			if not self.last_time:
-				self.last_time = now
-			self.next_wakeup = self.last_time + wait_time
-			# self.last_time is a very large value, and wait_time can be very small, so 
-			if self.next_wakeup - self.last_time < wait_time:
-				# due to floating point imprecision, it is possible for a nonzero wait-time to advance simulated time not enough to pop the next event, potentially even causing the model to hang, so we always take the ceil of the exact result of the addition self.last_time + wait_time.
-				self.next_wakeup = nextafter(self.next_wakeup, INFINITY)
-			remaining = max(self.next_wakeup - now, 0.0)
-			is_scheduled, self.scheduled_id = self.schedule_callback(f, remaining)
-		return is_scheduled
-
-	def clear(self):
-		if self.scheduled_id:
-			self.clear_callback(self.scheduled_id)
-			self.scheduled_id = None
-
-	def nextDelta(self):
-		now = time()
-		if self.next_wakeup:
-			simulated_now = self.next_wakeup
-		else:
-			simulated_now = now
-		if now - self.last_print > 1.0:
-			behind_schedule = now - simulated_now
-			if behind_schedule > 0.1:
-				print("Warning: running %.f ms behind schedule" % (behind_schedule*1000.0))
-				self.last_print = now
-		if self.last_time:
-			delta = simulated_now - self.last_time
-		else:
-			delta = 0.0
-		self.last_time = simulated_now
-		self.next_wakeup = None
-		return delta
-
-	# returns elapsed time since delta
-	def elapsed(self):
-		if self.last_time:
-			return time() - self.last_time
-		else:
-			return 0.0
-
-class EventLoopControllerBase(ControllerBase):
-	def __init__(self, object_manager, event_loop, finished_callback = None):
-		ControllerBase.__init__(self, object_manager)
-		self.event_loop = event_loop
-		self.finished_callback = finished_callback
-
-	def addInput(self, input_event, time_offset = 0.0):
-		elapsed = self.event_loop.elapsed()
-		controller_timeout = time_offset + elapsed
-		ControllerBase.addInput(self, input_event, controller_timeout)
-		if controller_timeout < self.event_loop.getScheduledTimeout():
-			# added event's timeout is sooner than existing timeout -> re-schedule
-			self.event_loop.clear()
-			if not self.event_loop.schedule(self.run, controller_timeout):
-				self.run()
-
-	def start(self):
-		ControllerBase.start(self)
-		self.run()
-
-	def stop(self):
-		self.event_loop.clear()
-		ControllerBase.stop(self)
-
-	def run(self):
-		while True:
-			# clear existing timeout
-			self.event_loop.clear()
-			# calculate last time since simulation
-			delta = self.event_loop.nextDelta()
-			# simulate
-			self.handleInput(delta)
-			self.object_manager.stepAll(delta)
-			# schedule next timeout
-			wait_time = self.getWaitTime()
-			scheduled = self.event_loop.schedule(self.run, wait_time)
-			if wait_time == INFINITY:
-				if self.finished_callback:
-					self.finished_callback()
-			if scheduled:
-				break
-		
-class ThreadsControllerBase(ControllerBase):
-	def __init__(self, object_manager, keep_running):
-		ControllerBase.__init__(self, object_manager)
-		self.keep_running = keep_running
-		self.input_condition = threading.Condition()
-		self.stop_thread = False
-		self.thread = threading.Thread(target=self.run)
-		
-	def handleInput(self, delta):
-		with self.input_condition:
-		    ControllerBase.handleInput(self, delta)
-		
-	def start(self):
-		self.thread.start()
-		
-	def stop(self):
-		with self.input_condition:
-		    self.stop_thread = True
-		    self.input_condition.notifyAll()
-
-	def getWaitTime(self):
-		"""Compute time untill earliest next event"""
-		with self.input_condition:
-		    wait_time = ControllerBase.getWaitTime(self)
-
-		if wait_time == INFINITY :
-			if self.done :
-				self.done = False
-			else :
-				self.done = True
-				return 0.0
-		return wait_time
-
-	def handleWaiting(self):
-		with self.input_condition:
-		    wait_time = self.getWaitTime()
-		    if(wait_time <= 0.0):
-			    return
-		    
-		    if wait_time == INFINITY :
-			    if self.keep_running :
-				    self.input_condition.wait() #Wait for a signals
-			    else :
-				    self.stop_thread = True
-		    
-		    elif wait_time != 0.0 :
-			    reduced_wait_time = wait_time - (time() - self.last_recorded_time)
-			    if reduced_wait_time > 0.0 :
-				    self.input_condition.wait(reduced_wait_time)    
-
-	def run(self):
-		self.last_recorded_time  = time()
-		super(ThreadsControllerBase, self).start()
-		last_iteration_time = 0.0
-		
-		while True:
-			with self.input_condition:
-			    self.handleInput(last_iteration_time)
-			#Compute the new state based on internal events
-			self.object_manager.stepAll(last_iteration_time)
-			
-			self.handleWaiting()
-			
-			with self.input_condition:
-			    if self.stop_thread : 
-				    break
-			
-			previous_recorded_time = self.last_recorded_time
-			self.last_recorded_time = time()
-			last_iteration_time = self.last_recorded_time - previous_recorded_time
-		
-	def join(self):
-		self.thread.join()
-
-	def addInput(self, input_event, time_offset = 0.0):
-		with self.input_condition:
-			super(ThreadsControllerBase, self).addInput(input_event, time_offset)
-			self.input_condition.notifyAll()
-
-	def addEventList(self, event_list):
-		with self.input_condition:
-			super(ThreadsControllerBase, self).addEventList(event_list)
-
-class StatechartSemantics:
-	# Big Step Maximality
-	TakeOne = 0
-	TakeMany = 1
-	# Concurrency - not implemented yet
-	Single = 0
-	Many = 1
-	# Preemption - not implemented yet
-	NonPreemptive = 0
-	Preemptive = 1
-	# Internal Event Lifeline
-	Queue = 0
-	NextSmallStep = 1
-	NextComboStep = 2
-	# Input Event Lifeline
-	Whole = 0
-	FirstSmallStep = 1
-	FirstComboStep = 2
-	# Priority
-	SourceParent = 0
-	SourceChild = 1
-	# TODO: add Memory Protocol options
-	
-	def __init__(self):
-		# default semantics:
-		self.big_step_maximality = self.TakeMany
-		self.concurrency = self.Single
-		self.internal_event_lifeline = self.Queue
-		#self.input_event_lifeline = self.FirstComboStep
-		self.input_event_lifeline = self.FirstSmallStep
-		self.priority = self.SourceParent
-
-class RuntimeClassBase(object):
-	__metaclass__  = abc.ABCMeta
-	
-	def __init__(self, controller):
-		self.active = False
-		self.is_stable = True
-		self.events = EventQueue()
-
-		self.controller = controller
-
-		self.timers = None
-		self.inports = {}
-
-		self.semantics = StatechartSemantics()
-
-	def start(self):
-		self.current_state = {}
-		self.history_state = {}
-		self.timers = {}
-
-		self.big_step = BigStepState()
-		self.combo_step = ComboStepState()
-		self.small_step = SmallStepState()
-
-		self.active = True
-		self.is_stable = False
-
-		self.initializeStatechart()
-		self.processBigStepOutput()
-	
-	def stop(self):
-		self.active = False
-		
-	def addEvent(self, event_list, time_offset = 0.0):
-		if not isinstance(event_list, list):
-			event_list = [event_list]
-		self.events.add(event_list, time_offset)
-		
-	def getEarliestEventTime(self) :
-		if not self.active:
-			return INFINITY
-		if not self.is_stable:
-			return 0.0
-		if self.timers:
-			return min(self.events.getEarliestTime(), min(self.timers.values()))
-		return self.events.getEarliestTime()
-
-	def processBigStepOutput(self):
-		for e in self.big_step.getOutputEvents():
-			self.controller.outputEvent(e)
-		for e in self.big_step.getOutputEventsOM():
-			self.controller.object_manager.addEvent(e)
-
-	def step(self, delta):
-		if not self.active :
-			return
-		
-		# decrease event queue time
-		self.events.decreaseTime(delta)
-
-		# decrease timers time
-		next_timers = {}
-		for (key,value) in list(self.timers.items()):
-			time = value - delta
-			if time <= 0.0 :
-				self.addEvent( Event("_" + str(key) + "after"), time)
-			else :
-				next_timers[key] = time
-		self.timers = next_timers
-
-		# execute big step(s)
-		due = self.events.popDueEvents()
-		if not due and not self.is_stable:
-			due = [[]]
-		for input_events in due:
-			# perform 1 big step per slot in 'due'
-			self.is_stable = not self.bigStep(input_events)
-			self.processBigStepOutput()
-
-	def inState(self, nodes):
-		for c in list(self.current_state.values()):
-			new_nodes = []
-			for n in nodes:
-				if not (n in c):
-					new_nodes.append(n)
-			nodes = new_nodes
-			if len(nodes) == 0:
-				return True
-		return False
-
-	def bigStep(self, input_events):
-		#print "new big step"
-		self.big_step.next(input_events)
-		self.small_step.reset()
-		self.combo_step.reset()
-		while self.comboStep():
-			self.big_step.setStepped()
-			if self.semantics.big_step_maximality == StatechartSemantics.TakeOne:
-				break # Take One -> only one combo step allowed
-		return self.big_step.hasStepped()
-
-	def comboStep(self):
-		#print "new combo step"
-		self.combo_step.next()
-		while self.smallStep():
-			self.combo_step.setStepped()
-		return self.combo_step.hasStepped()
-
-	def smallStep(self):
-		if self.small_step.hasStepped():
-			self.small_step.next()
-		self.generateCandidates()
-		if self.small_step.hasCandidates():
-			#print "new small step, have " + str(len(self.small_step.getCandidates())) + " candidates"
-			if self.semantics.concurrency == StatechartSemantics.Single:
-				transition, parameters = self.small_step.getCandidates()[0] # execute first of candidates
-				transition(parameters)
-			elif self.semantics.concurrency == StatechartSemantics.Many:
-				pass # TODO: implement
-			self.small_step.setStepped()
-		return self.small_step.hasStepped()
-
-	def getEnabledEvents(self):
-		result = self.small_step.getCurrentEvents() + self.combo_step.getCurrentEvents()
-		if self.semantics.input_event_lifeline == StatechartSemantics.Whole or (
-			not self.big_step.hasStepped() and
-				(self.semantics.input_event_lifeline == StatechartSemantics.FirstComboStep or (
-				not self.combo_step.hasStepped() and
-					self.semantics.input_event_lifeline == StatechartSemantics.FirstSmallStep))):
-			result += self.big_step.getInputEvents()
-		return result
-
-	def raiseInternalEvent(self, event):
-		if self.semantics.internal_event_lifeline == StatechartSemantics.NextSmallStep:
-			self.small_step.addNextEvent(event)
-		elif self.semantics.internal_event_lifeline == StatechartSemantics.NextComboStep:
-			self.combo_step.addNextEvent(event)
-		elif self.semantics.internal_event_lifeline == StatechartSemantics.Queue:
-			self.events.add([event], 0.0)
-
-	@abc.abstractmethod
-	def initializeStatechart(self):
-		pass
-
-	@abc.abstractmethod
-	def generateCandidates(self):
-		pass
-
-
-class BigStepState(object):
-	def __init__(self):
-		self.input_events = [] # input events received from environment before beginning of big step (e.g. from object manager, from input port)
-		self.output_events_port = [] # output events to be sent to output port after big step ends.
-		self.output_events_om = [] # output events to be sent to object manager after big step ends.
-		self.has_stepped = True
-
-	def next(self, input_events):
-		self.input_events = input_events
-		self.output_events_port = []
-		self.output_events_om = []
-		self.has_stepped = False
-
-	def getInputEvents(self):
-		return self.input_events
-
-	def getOutputEvents(self):
-		return self.output_events_port
-
-	def getOutputEventsOM(self):
-		return self.output_events_om
-
-	def outputEvent(self, event):
-		self.output_events_port.append(event)
-
-	def outputEventOM(self, event):
-		self.output_events_om.append(event)
-
-	def setStepped(self):
-		self.has_stepped = True
-
-	def hasStepped(self):
-		return self.has_stepped
-
-
-class ComboStepState(object):
-	def __init__(self):
-		self.current_events = [] # set of enabled events during combo step
-		self.next_events = [] # internal events that were raised during combo step
-		self.changed = [] # set of all or-states that were the arena of a triggered transition during big step.
-		self.has_stepped = True
-
-	def reset(self):
-		self.current_events = []
-		self.next_events = []
-
-	def next(self):
-		self.current_events = self.next_events
-		self.next_events = []
-		self.changed = []
-		self.has_stepped = False
-
-	def addNextEvent(self, event):
-		self.next_events.append(event)
-
-	def getCurrentEvents(self):
-		return self.current_events
-
-	def setArenaChanged(self, arena):
-		self.changed.append(arena)
-
-	def isArenaChanged(self, arena):
-		return (arena in self.changed)
-
-	def isStable(self):
-		return (len(self.changed) == 0)
-
-	def setStepped(self):
-		self.has_stepped = True
-
-	def hasStepped(self):
-		return self.has_stepped
-
-
-class SmallStepState(object):
-	def __init__(self):
-		self.current_events = [] # set of enabled events during small step
-		self.next_events = [] # events to become 'current' in the next small step
-		self.candidates = [] # document-ordered(!) list of transitions that can potentially be executed concurrently, or preempt each other, depending on concurrency semantics. If no concurrency is used and there are multiple candidates, the first one is chosen. Source states of candidates are *always* orthogonal to each other.
-		self.has_stepped = True
-
-	def reset(self):
-		self.current_events = []
-		self.next_events = []
-
-	def next(self):
-		self.current_events = self.next_events # raised events from previous small step
-		self.next_events = []
-		self.candidates = []
-		self.has_stepped = False
-
-	def addNextEvent(self, event):
-		self.next_events.append(event)
-
-	def getCurrentEvents(self):
-		return self.current_events
-
-	def addCandidate(self, t, p):
-		self.candidates.append((t, p))
-
-	def getCandidates(self):
-		return self.candidates
-
-	def hasCandidates(self):
-		return len(self.candidates) > 0
-
-	def setStepped(self):
-		self.has_stepped = True
-
-	def hasStepped(self):
-		return self.has_stepped
-

+ 0 - 21
kernel/mvk_server/python_runtime/tkinter_eventloop.py

@@ -1,21 +0,0 @@
-from kernel.mvk_server.python_runtime.statecharts_core import EventLoop
-import math
-
-class TkEventLoop(EventLoop):
-	def __init__(self, tk):
-	
-		tk.sccd_force_update = False
-
-		# bind scheduler callback
-		def schedule(callback, timeout):
-			if timeout == 0:
-			# tk considers updating the window an 'idle' task, only to be done if no events are scheduled for a while. But this has the downside of the interface becoming completely unresponsive while the model is performing steps with no gaps in between. Thus we insert an 'update_idletasks()' to obtain "javascript event loop"-like behavior.
-				if tk.sccd_force_update:
-					tk.update_idletasks()
-					tk.sccd_force_update = False
-				else:
-					return (False, None) # don't schedule 0-timeout, it's more performant to just keep running
-			return (True, tk.after(int(math.ceil(timeout*1000.0)), callback))
-
-		EventLoop.__init__(self, schedule, tk.after_cancel)
-

+ 0 - 17
kernel/mvk_server/python_sccd_compiler/.project

@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-	<name>python_sccd_compiler</name>
-	<comment></comment>
-	<projects>
-	</projects>
-	<buildSpec>
-		<buildCommand>
-			<name>org.python.pydev.PyDevBuilder</name>
-			<arguments>
-			</arguments>
-		</buildCommand>
-	</buildSpec>
-	<natures>
-		<nature>org.python.pydev.pythonNature</nature>
-	</natures>
-</projectDescription>

+ 0 - 5
kernel/mvk_server/python_sccd_compiler/.pydevproject

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<?eclipse-pydev version="1.0"?><pydev_project>
-<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
-<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
-</pydev_project>

+ 0 - 0
kernel/mvk_server/python_sccd_compiler/__init__.py


+ 0 - 14
kernel/mvk_server/python_sccd_compiler/compiler_exceptions.py

@@ -1,14 +0,0 @@
-class CompilerException(Exception):
-	def __init__(self, message):
-		self.message = message
-	def __str__(self):
-		return repr(self.message)
-	
-class TransitionException(CompilerException):
-	pass
-
-class UnprocessedException(CompilerException):
-	pass
-
-class CodeBlockException(CompilerException):
-	pass

+ 0 - 911
kernel/mvk_server/python_sccd_compiler/generic_generator.py

@@ -1,911 +0,0 @@
-# Generic Generator by Joeri Exelmans
-#
-# Visits SCCD-domain constructs (see sccd_constructs.py) and converts them
-# to a generic language AST (see generic_language_constructs.py), that can
-# then be visited by a target language writer.
-
-import traceback
-
-import time
-from kernel.mvk_server.python_sccd_compiler.utils import Enum, Logger
-
-from kernel.mvk_server.python_sccd_compiler.visitor import Visitor
-from kernel.mvk_server.python_sccd_compiler.sccd_constructs import FormalParameter
-from kernel.mvk_server.python_sccd_compiler.stateful_writer import StatefulWriter
-import kernel.mvk_server.python_sccd_compiler.generic_language_constructs as GLC
-
-Platforms = Enum("Threads","GameLoop","EventLoop") 
-
-class GenericGenerator(Visitor):
-	
-	def __init__(self, platform):
-		self.platform = platform
-		self.writer = StatefulWriter()
-
-	def generic_visit(self, node):
-		Logger.showWarning("GenericGenerator has no visit method for node of type '" + str(type(node)) + "'.")
-
-	def get(self):
-		return self.writer.get()
-
-	def visit_ClassDiagram(self, class_diagram):
-		header = ("Generated by Statechart compiler by Glenn De Jonghe and Joeri Exelmans\n"
-		          "\n"
-		          "Date:   " + time.asctime() + "\n")
-		if class_diagram.name or class_diagram.author or class_diagram.description:
-			header += "\n"
-		if class_diagram.author:
-			header += "Model author: " + class_diagram.author + "\n"
-		if class_diagram.name:
-			header += "Model name:   " + class_diagram.name + "\n"
-		if class_diagram.description.strip():
-			header += "Model description:\n"
-			header += class_diagram.description.strip()
-
-		self.writer.addMultiLineComment(header)
-		self.writer.addVSpace()
-		self.writer.addInclude(([GLC.RuntimeModuleIdentifier(), "statecharts_core"]))
-		if class_diagram.top.strip():
-			self.writer.addRawCode(class_diagram.top)
-		self.writer.addVSpace()
-
-		self.writer.beginPackage(class_diagram.name)
-		
-		#visit children
-		for c in class_diagram.classes :
-			c.accept(self)
-		 
-		self.writer.beginClass("ObjectManager", ["ObjectManagerBase"])
-
-		self.writer.beginConstructor()
-		self.writer.addFormalParameter("controller")
-		self.writer.beginMethodBody()
-		self.writer.beginSuperClassConstructorCall("ObjectManagerBase")
-		self.writer.addActualParameter("controller")
-		self.writer.endSuperClassConstructorCall()
-		self.writer.endMethodBody()
-		self.writer.endConstructor()
-
-		self.writer.beginMethod("instantiate")
-		self.writer.addFormalParameter("class_name")
-		self.writer.addFormalParameter("construct_params")
-		self.writer.beginMethodBody()
-		for index,c in enumerate(class_diagram.classes):
-			self.writer.beginElseIf(GLC.EqualsExpression("class_name", GLC.String(c.name)))
-			if c.isAbstract():
-				# cannot instantiate abstract class
-				self.writer.add(GLC.ThrowExceptionStatement(GLC.String("Cannot instantiate abstract class \"" + c.name + "\" with unimplemented methods \"" + "\", \"".join(c.abstract_method_names) + "\".")))
-			else:
-				new_expr = GLC.NewExpression(c.name, [GLC.SelfProperty("controller")])
-				param_count = 0
-				for p in c.constructors[0].parameters:
-					new_expr.getActualParameters().add(GLC.ArrayIndexedExpression("construct_params", str(param_count)))
-					param_count += 1
-				self.writer.addAssignment(
-					GLC.LocalVariableDeclaration("instance"),
-					new_expr)
-				self.writer.addAssignment(
-					GLC.Property("instance", "associations"),
-					GLC.MapExpression())
-				for a in c.associations:
-					a.accept(self)
-			self.writer.endElseIf()
-		self.writer.add(GLC.ReturnStatement("instance"))
-		self.writer.endMethodBody()
-		self.writer.endMethod()
-		self.writer.endClass() # ObjectManager
-
-		if self.platform == Platforms.Threads:
-			controller_sub_class = "ThreadsControllerBase"
-		if self.platform == Platforms.EventLoop :
-			controller_sub_class = "EventLoopControllerBase"
-		elif self.platform == Platforms.GameLoop :
-			controller_sub_class = "GameLoopControllerBase"
-
-		self.writer.beginClass("Controller", [controller_sub_class])
-		self.writer.beginConstructor()
-		for p in class_diagram.default_class.constructors[0].parameters:
-			p.accept(self)
-		if self.platform == Platforms.EventLoop:
-			self.writer.addFormalParameter("event_loop_callbacks")
-			self.writer.addFormalParameter("finished_callback", GLC.NoneExpression())
-		elif self.platform == Platforms.Threads:
-			self.writer.addFormalParameter("keep_running", GLC.TrueExpression())
-		self.writer.beginMethodBody()
-		self.writer.beginSuperClassConstructorCall(controller_sub_class)
-		self.writer.addActualParameter(GLC.NewExpression("ObjectManager", [GLC.SelfExpression()]))
-		if self.platform == Platforms.EventLoop:
-			self.writer.addActualParameter("event_loop_callbacks")
-			self.writer.addActualParameter("finished_callback")
-		elif self.platform == Platforms.Threads:
-			self.writer.addActualParameter("keep_running")
-		self.writer.endSuperClassConstructorCall()
-		for i in class_diagram.inports:
-			self.writer.add(GLC.FunctionCall(GLC.SelfProperty("addInputPort"), [GLC.String(i)]))
-		for o in class_diagram.outports:
-			self.writer.add(GLC.FunctionCall(GLC.SelfProperty("addOutputPort"), [GLC.String(o)]))
-		actual_parameters = [p.getIdent() for p in class_diagram.default_class.constructors[0].parameters]
-		self.writer.add(GLC.FunctionCall(GLC.Property(GLC.SelfProperty("object_manager"), "createInstance"), [GLC.String(class_diagram.default_class.name), GLC.ArrayExpression(actual_parameters)]))
-		self.writer.endMethodBody()
-		self.writer.endConstructor()
-		self.writer.endClass() # Controller
-
-		# Visit test node if there is one
-		if class_diagram.test:
-			class_diagram.test.accept(self)
-
-		self.writer.endPackage()
-
-	def visit_DiagramTest(self, test):
-		# helper class
-		self.writer.beginClass("InputEvent")
-		self.writer.beginConstructor()
-		self.writer.addFormalParameter("name")
-		self.writer.addFormalParameter("port")
-		self.writer.addFormalParameter("parameters")
-		self.writer.addFormalParameter("time_offset")
-		self.writer.beginMethodBody()
-		self.writer.addAssignment(GLC.SelfProperty("name"), "name")
-		self.writer.addAssignment(GLC.SelfProperty("port"), "port")
-		self.writer.addAssignment(GLC.SelfProperty("parameters"), "parameters")
-		self.writer.addAssignment(GLC.SelfProperty("time_offset"), "time_offset")
-		self.writer.endMethodBody()
-		self.writer.endConstructor()
-		self.writer.endClass()
-		self.writer.beginClass("Test")
-		if test.input:
-			test.input.accept(self)
-		else:
-			self.writer.addStaticAttribute("input_events", GLC.ArrayExpression())
-		if test.expected:
-			test.expected.accept(self)
-		else:
-			self.writer.addStaticAttribute("expected_events", GLC.ArrayExpression())
-		self.writer.endClass()
-
-	def visit_DiagramTestInput(self, test_input):
-		# write array of input events
-		self.writer.startRecordingExpression()
-		self.writer.beginArray()
-		for e in test_input.input_events:
-			e.accept(self)
-		self.writer.endArray()
-		array_expr = self.writer.stopRecordingExpression()
-		self.writer.addStaticAttribute("input_events", array_expr)
-
-	def visit_DiagramTestInputEvent(self, event):
-		self.writer.add(GLC.NewExpression("InputEvent", [GLC.String(event.name), GLC.String(event.port), GLC.ArrayExpression(event.parameters), event.time]))
-
-	def visit_DiagramTestExpected(self, test_expected):
-		# write array of slots containing expected events
-		self.writer.startRecordingExpression()
-		self.writer.beginArray()
-		for s in test_expected.slots:
-			s.accept(self)
-		self.writer.endArray()
-		array_expr = self.writer.stopRecordingExpression()
-		self.writer.addStaticAttribute("expected_events", array_expr)
-
-	def visit_DiagramTestExpectedSlot(self, slot):
-		# write slot
-		self.writer.beginArray()
-		for e in slot.expected_events:
-			e.accept(self)
-		self.writer.endArray()
-
-	def visit_DiagramTestEvent(self, event):
-		self.writer.add(GLC.NewExpression("Event", [GLC.String(event.name), GLC.String(event.port), GLC.ArrayExpression(event.parameters)]))
-
-	def visit_Class(self, class_node):
-		"""
-		Generate code for Class construct
-		"""
-
-		super_classes = []
-		if not class_node.super_class_objs:
-			# if none of the class' super classes is defined in the diagram,
-			# we have to inherit RuntimeClassBase
-			if class_node.statechart:
-				# only inherit RuntimeClassBase if class has a statechart
-				super_classes.append("RuntimeClassBase")
-		if class_node.super_classes:
-			for super_class in class_node.super_classes:
-				super_classes.append(super_class)
-
-		self.writer.beginClass(class_node.name, super_classes)
-
-		#visit constructor
-		for i in class_node.constructors :
-			i.accept(self)
-
-		self.writer.beginMethod("user_defined_constructor")
-		for p in class_node.constructors[0].getParams():
-			p.accept(self)
-		self.writer.beginMethodBody()
-		for super_class in class_node.super_classes:
-			# begin call
-			if super_class in class_node.super_class_objs:
-				self.writer.beginSuperClassMethodCall(super_class, "user_defined_constructor")
-			else:
-				self.writer.beginSuperClassConstructorCall(super_class)
-			# write actual parameters
-			if super_class in class_node.constructors[0].super_class_parameters:
-				for p in class_node.constructors[0].super_class_parameters[super_class]:
-					self.writer.addActualParameter(p)
-			# end call
-			if super_class in class_node.super_class_objs:
-				self.writer.endSuperClassMethodCall()
-			else:
-				self.writer.endSuperClassConstructorCall()
-		self.writer.addRawCode(class_node.constructors[0].body)
-		self.writer.endMethodBody()
-		self.writer.endMethod()
-
-
-		#visit children
-		for i in class_node.destructors :
-			i.accept(self)
-		for i in class_node.methods :
-			i.accept(self)
-
-		if class_node.statechart:
-			self.writer.beginMethod("initializeStatechart")
-			self.writer.beginMethodBody()
-
-			for c in class_node.statechart.composites :
-				self.writer.addAssignment(GLC.MapIndexedExpression(GLC.SelfProperty("current_state"), GLC.SelfProperty(c.full_name)), GLC.ArrayExpression())
-
-			if class_node.statechart.histories:
-				self.writer.addVSpace()
-				for node in class_node.statechart.combined_history_parents:
-					self.writer.addAssignment(GLC.MapIndexedExpression(GLC.SelfProperty("history_state"), GLC.SelfProperty(node.full_name)), GLC.ArrayExpression())
-
-			self.writer.addVSpace()
-			self.writer.addComment("Enter default state")	
-			for default_node in class_node.statechart.root.defaults:
-				if default_node.is_composite:
-					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterDefault_"+default_node.full_name)))
-				elif default_node.is_basic:
-					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_"+default_node.full_name)))
-			self.writer.endMethodBody()
-			self.writer.endMethod()
-
-			class_node.statechart.accept(self)
-
-		self.writer.endClass()
-
-
-	def visit_FormalParameter(self, formal_parameter):
-		self.writer.addFormalParameter(formal_parameter.getIdent(), formal_parameter.getDefault())
-		
-	def visit_Constructor(self, constructor):
-		self.writer.beginConstructor()
-		if constructor.parent_class.statechart:
-			self.writer.addFormalParameter("controller")
-		for p in constructor.getParams():
-			self.writer.addFormalParameter(p.getIdent(), p.getDefault())
-		self.writer.beginMethodBody() # constructor body
-
-		if constructor.parent_class.statechart:
-			self.writer.beginSuperClassConstructorCall("RuntimeClassBase")
-			self.writer.addActualParameter("controller")
-			self.writer.endSuperClassConstructorCall()
-
-			self.writer.addVSpace()
-
-			if constructor.parent_class.statechart.big_step_maximality == "take_one":
-				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "big_step_maximality"), GLC.Property("StatechartSemantics", "TakeOne"))
-			elif constructor.parent_class.statechart.big_step_maximality == "take_many":
-				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "big_step_maximality"), GLC.Property("StatechartSemantics", "TakeMany"))
-
-			if constructor.parent_class.statechart.internal_event_lifeline == "queue":
-				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "internal_event_lifeline"), GLC.Property("StatechartSemantics", "Queue"))
-			elif constructor.parent_class.statechart.internal_event_lifeline == "next_small_step":
-				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "internal_event_lifeline"), GLC.Property("StatechartSemantics", "NextSmallStep"))
-			elif constructor.parent_class.statechart.internal_event_lifeline == "next_combo_step":
-				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "internal_event_lifeline"), GLC.Property("StatechartSemantics", "NextComboStep"))
-
-			if constructor.parent_class.statechart.input_event_lifeline == "first_small_step":
-				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "input_event_lifeline"), GLC.Property("StatechartSemantics", "FirstSmallStep"))
-			elif constructor.parent_class.statechart.input_event_lifeline == "first_combo_step":
-				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "input_event_lifeline"), GLC.Property("StatechartSemantics", "FirstComboStep"))
-			elif constructor.parent_class.statechart.input_event_lifeline == "whole":
-				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "input_event_lifeline"), GLC.Property("StatechartSemantics", "Whole"))
-
-			if constructor.parent_class.statechart.priority == "source_parent":
-				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "priority"), GLC.Property("StatechartSemantics", "SourceParent"))
-			elif constructor.parent_class.statechart.priority == "source_child":
-				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "priority"), GLC.Property("StatechartSemantics", "SourceChild"))
-
-
-			if constructor.parent_class.statechart.concurrency == "single":
-				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "concurrency"), GLC.Property("StatechartSemantics", "Single"))
-			elif constructor.parent_class.statechart.concurrency == "many":
-				self.writer.addAssignment(GLC.Property(GLC.SelfProperty("semantics"), "concurrency"), GLC.Property("StatechartSemantics", "Many"))
-
-		for p in constructor.parent_class.inports:
-			self.writer.addAssignment(
-				GLC.MapIndexedExpression(GLC.SelfProperty("inports"), GLC.String(p)),
-				GLC.FunctionCall(GLC.Property("controller", "addInputPort"), [GLC.String(p), GLC.SelfExpression()]))
-
-		if constructor.parent_class.attributes:
-			self.writer.addVSpace()
-			self.writer.addComment("User defined attributes")
-			for attribute in constructor.parent_class.attributes:
-				if attribute.init_value is None :
-					self.writer.addAssignment(GLC.SelfProperty(attribute.name), GLC.NoneExpression())
-				else :
-					self.writer.addAssignment(GLC.SelfProperty(attribute.name), attribute.init_value)
-
-		self.writer.addVSpace()
-		self.writer.addComment("Call user defined constructor")
-		self.writer.beginSuperClassMethodCall(constructor.parent_class.name, "user_defined_constructor")
-		for p in constructor.getParams():
-			# we can't do p.accept(self) here because 'p' is a FormalParameter
-			# and we want to write it as an actual parameter
-			self.writer.addActualParameter(p.getIdent())
-		self.writer.endSuperClassMethodCall()
-		self.writer.endMethodBody()
-		self.writer.endConstructor()
-
-	def visit_Destructor(self, destructor):
-		self.writer.beginMethod("user_defined_destructor")
-		self.writer.beginMethodBody()
-		if destructor.body.strip():
-			self.writer.addRawCode(destructor.body)
-		if destructor.parent_class.super_classes:
-			self.writer.addComment("Call super class destructors")
-			for super_class in destructor.parent_class.super_classes:
-				# begin call
-				if super_class in destructor.parent_class.super_class_objs:
-					self.writer.beginSuperClassMethodCall(super_class, "user_defined_destructor")
-					self.writer.endSuperClassMethodCall()
-				else:
-					self.writer.beginSuperClassDestructorCall(super_class)
-					self.writer.endSuperClassDestructorCall()
-					pass
-
-				#self.writer.beginSuperClassMethodCall(super_class, "user_defined_destructor")
-				#self.writer.endSuperClassMethodCall()
-		self.writer.endMethodBody()
-		self.writer.endMethod()
-		
-	def visit_Method(self, method):
-		self.writer.addVSpace()
-		self.writer.beginMethod(method.name, "User defined method")
-		for p in method.parameters:
-			p.accept(self)
-		self.writer.beginMethodBody()
-		self.writer.addRawCode(method.body)
-		self.writer.endMethodBody()
-		self.writer.endMethod()
-		
-	def visit_Association(self, association):
-		self.writer.addAssignment(
-			GLC.MapIndexedExpression(
-				GLC.Property("instance", "associations"),
-				GLC.String(association.name)),
-			GLC.NewExpression("Association", [GLC.String(association.to_class), str(association.min), str(association.max)]))
-
-	#helper method
-	def writeTransitionsRecursively(self, current_node):
-		valid_children = []
-		for child in current_node.children :
-			if child.is_composite or child.is_basic :
-				valid_children.append(child)
-
-		has_candidates_children = (len(valid_children) > 0)
-		has_candidates_current = (len(current_node.transitions) > 0)
-
-		if has_candidates_children:
-			self.writer.beginMethod("generateCandidatesChildren_" + current_node.full_name)
-			self.writer.beginMethodBody()
-			if current_node.is_parallel_state:
-				self.writer.addAssignment(
-					GLC.LocalVariableDeclaration("branch_done"),
-					GLC.FalseExpression())
-				for child in valid_children :
-					self.writer.addAssignment(
-						"branch_done",
-						GLC.OrExpression(
-							GLC.FunctionCall(GLC.SelfProperty("generateCandidates_" + child.full_name)),
-							"branch_done"))
-				self.writer.add(GLC.ReturnStatement("branch_done"))
-			elif current_node.is_composite:
-				for i, child in enumerate(valid_children) :
-					self.writer.beginElseIf(GLC.EqualsExpression(
-						GLC.ArrayIndexedExpression(
-							GLC.MapIndexedExpression(
-								GLC.SelfProperty("current_state"),
-								GLC.SelfProperty(current_node.full_name)),
-							"0"),
-						GLC.SelfProperty(child.full_name)))
-					self.writer.add(GLC.ReturnStatement(GLC.FunctionCall(GLC.SelfProperty("generateCandidates_"+child.full_name))))
-					self.writer.endElseIf()
-				self.writer.add(GLC.ReturnStatement(GLC.FalseExpression()))
-			self.writer.endMethodBody()
-			self.writer.endMethod()
-
-		if has_candidates_current:
-			self.writer.beginMethod("generateCandidatesCurrent_" + current_node.full_name)
-			self.writer.beginMethodBody()
-			self.writeFromTransitions(current_node)
-			self.writer.add(GLC.ReturnStatement(GLC.FalseExpression()))
-			self.writer.endMethodBody()
-			self.writer.endMethod()
-
-		self.writer.beginMethod("generateCandidates_" + current_node.full_name)
-		self.writer.beginMethodBody()
-
-		if not has_candidates_children and not has_candidates_current:
-			self.writer.add(GLC.ReturnStatement(GLC.FalseExpression()))
-		else:
-			self.writer.beginIf(
-				GLC.NotExpression(GLC.FunctionCall(
-					GLC.Property(GLC.SelfProperty("combo_step"), "isArenaChanged"),
-					[GLC.SelfProperty(current_node.full_name)])))
-
-			if has_candidates_children and has_candidates_current:
-				self.writer.addAssignment(
-					GLC.LocalVariableDeclaration("branch_done"),
-					GLC.FalseExpression())
-
-			if not has_candidates_children and has_candidates_current:
-				self.writer.add(GLC.ReturnStatement(GLC.FunctionCall(GLC.SelfProperty("generateCandidatesCurrent_" + current_node.full_name))))
-			elif not has_candidates_current and has_candidates_children:
-				self.writer.add(GLC.ReturnStatement(GLC.FunctionCall(GLC.SelfProperty("generateCandidatesChildren_" + current_node.full_name))))
-			else:
-				self.writer.beginElseIf(GLC.EqualsExpression(
-					GLC.Property(GLC.SelfProperty("semantics"), "priority"),
-					GLC.Property("StatechartSemantics", "SourceParent")))
-				if has_candidates_current:
-					self.writer.addAssignment("branch_done", GLC.FunctionCall(GLC.SelfProperty("generateCandidatesCurrent_" + current_node.full_name)))
-				if has_candidates_children:
-					self.writer.beginIf(GLC.NotExpression("branch_done"))
-					self.writer.addAssignment("branch_done", GLC.FunctionCall(GLC.SelfProperty("generateCandidatesChildren_" + current_node.full_name)))
-					self.writer.endIf()
-				self.writer.endElseIf()
-				self.writer.beginElseIf(GLC.EqualsExpression(
-					GLC.Property(GLC.SelfProperty("semantics"), "priority"),
-					GLC.Property("StatechartSemantics", "SourceChild")))
-				if has_candidates_children:
-					self.writer.addAssignment("branch_done", GLC.FunctionCall(GLC.SelfProperty("generateCandidatesChildren_" + current_node.full_name)))
-				if has_candidates_current:
-					self.writer.beginIf(GLC.NotExpression("branch_done"))
-					self.writer.addAssignment("branch_done", GLC.FunctionCall(GLC.SelfProperty("generateCandidatesCurrent_" + current_node.full_name)))
-					self.writer.endIf()
-				self.writer.endElseIf()
-
-			if has_candidates_children and has_candidates_current:
-				self.writer.add(GLC.ReturnStatement("branch_done"))
-			self.writer.endIf()
-			self.writer.beginElse()
-			self.writer.add(GLC.ReturnStatement(GLC.TrueExpression()))
-			self.writer.endElse()
-
-		self.writer.endMethodBody()
-		self.writer.endMethod()
-
-		for index, transition in enumerate(current_node.transitions, start=1):
-			self.writeTransitionAction(transition, index)
-		
-		for child in valid_children :
-			self.writeTransitionsRecursively(child)
-				
-	#helper method
-	def writeFromTransitions(self, current_node): 
-		# get all transition out of this state
-		out_transitions = current_node.transitions
-		if len(out_transitions) == 0 :
-			return
-		
-		for index, transition in enumerate(out_transitions, start=1):
-			self.writeTransitionCondition(transition, index)
-		
-	def visit_FormalEventParameter(self, formal_event_parameter):
-		self.writer.add(formal_event_parameter.name)
-		
-	def writeFormalEventParameters(self, transition):
-		parameters = transition.getTrigger().getParameters()
-		if(len(parameters) > 0) :
-			for index, parameter in enumerate(parameters):
-				self.writer.startRecordingExpression()
-				parameter.accept(self)
-				parameter_expr = self.writer.stopRecordingExpression()
-				self.writer.addAssignment(
-					GLC.LocalVariableDeclaration(parameter_expr),
-					GLC.ArrayIndexedExpression("parameters", str(index)))
-		
-		
-	def writeTransitionAction(self, transition, index):
-		self.writer.beginMethod("transition_" + transition.parent_node.full_name + "_" + str(index))
-		self.writer.addFormalParameter("parameters")
-		self.writer.beginMethodBody()
-
-		# handle parameters to actually use them
-		self.writeFormalEventParameters(transition)
-		
-		exits = transition.getExitNodes()
-		
-		# write exit actions
-		if not exits[-1].is_basic:
-			self.writer.add(GLC.FunctionCall(GLC.SelfProperty("exit_"+exits[-1].full_name)))
-		else:
-			for node in exits:
-				if node.is_basic:
-					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("exit_"+node.full_name)))
-					
-		# write trigger actions
-		transition.getAction().accept(self)
-
-		# add arena of transition to list of 'changed' states,
-		# this may prevent other transitions whose arenas overlap to be taken
-		self.writer.add(
-			GLC.FunctionCall(
-				GLC.Property(GLC.SelfProperty("combo_step"), "setArenaChanged"),
-				[GLC.SelfProperty(transition.arena.full_name)]))
-
-		# write enter actions
-		for (entering_node, is_ending_node) in transition.getEnterNodes() : 
-			if is_ending_node :
-				if entering_node.is_composite:
-					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterDefault_" + entering_node.full_name)))
-				elif entering_node.is_history:
-					if (entering_node.is_history_deep) :
-						self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterHistoryDeep_" + entering_node.parent.full_name)))
-					else :
-						self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterHistoryShallow_" + entering_node.parent.full_name)))
-				else:
-					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_" + entering_node.full_name)))
-			else :
-				if entering_node.is_composite:
-					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_" + entering_node.full_name)))
-
-		self.writer.endMethodBody()
-		self.writer.endMethod()
-						
-	def writeTransitionCondition(self, transition, index):
-		trigger = transition.getTrigger()
-
-		self.writer.addAssignment(
-			GLC.LocalVariableDeclaration("enabled_events"),
-			GLC.FunctionCall(GLC.SelfProperty("getEnabledEvents")))
-
-		if not trigger.isUC():
-			self.writer.beginForLoopIterateArray("enabled_events", "e")
-			condition = GLC.EqualsExpression(
-				GLC.Property(GLC.ForLoopCurrentElement("enabled_events", "e"), "name"),
-					GLC.String(trigger.getEvent()))
-			if trigger.getPort() != "":
-				condition = GLC.AndExpression(
-					condition,
-					GLC.EqualsExpression(
-						GLC.Property(GLC.ForLoopCurrentElement("enabled_events", "e"), "port"),
-						GLC.String(trigger.getPort())))
-			self.writer.beginIf(condition)
-		# evaluate guard
-		if transition.hasGuard() :
-			# handle parameters for guard evaluation
-			if not transition.getTrigger().isUC():
-				self.writer.addAssignment(GLC.LocalVariableDeclaration("parameters"), GLC.Property(GLC.ForLoopCurrentElement("enabled_events", "e"), "parameters"))
-				self.writeFormalEventParameters(transition)
-			self.writer.startRecordingExpression()
-			transition.getGuard().accept(self) # --> visit_Expression
-			expr = self.writer.stopRecordingExpression()
-			self.writer.beginIf(expr)
-
-		if trigger.isUC():
-			params_expr = GLC.ArrayExpression()
-		else:
-			params_expr = GLC.Property(GLC.ForLoopCurrentElement("enabled_events", "e"), "parameters")
-		self.writer.add(GLC.FunctionCall(GLC.Property(GLC.SelfProperty("small_step"), "addCandidate"), [GLC.SelfProperty("transition_" + transition.parent_node.full_name + "_" + str(index)), params_expr]))
-
-		self.writer.add(GLC.ReturnStatement(GLC.TrueExpression()))
-
-		if transition.hasGuard() :
-			self.writer.endIf()
-		if not trigger.isUC() :
-			self.writer.endIf()
-			self.writer.endForLoopIterateArray()
-	
-	def visit_EnterAction(self, enter_method):
-		parent_node = enter_method.parent_node
-		self.writer.beginMethod("enter_" + parent_node.full_name)
-		self.writer.beginMethodBody()
-
-		# take care of any AFTER events
-		for transition in parent_node.transitions :
-			trigger = transition.getTrigger()
-			if trigger.isAfter() :
-				self.writer.startRecordingExpression()
-				trigger.after.accept(self)
-				after = self.writer.stopRecordingExpression()
-				
-				self.writer.addAssignment(
-					GLC.MapIndexedExpression(GLC.SelfProperty("timers"), str(trigger.getAfterIndex())),
-					after)
-
-		if enter_method.action:
-			enter_method.action.accept(self)
-		self.writer.add(
-			GLC.ArrayPushBack(
-					GLC.MapIndexedExpression(
-						GLC.SelfProperty("current_state"),
-						GLC.SelfProperty(parent_node.parent.full_name)),
-					GLC.SelfProperty(parent_node.full_name)))
-		self.writer.endMethodBody()
-		self.writer.endMethod()
-		
-	#helper method
-	def writeEnterDefault(self, entered_node):
-		self.writer.beginMethod("enterDefault_" + entered_node.full_name)
-		self.writer.beginMethodBody()
-		self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_"+entered_node.full_name)))
-		if entered_node.is_composite:
-			l = entered_node.defaults
-			for i in l:
-				if i.is_composite:
-					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterDefault_" + i.full_name)))
-				elif i.is_basic:
-					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_" + i.full_name)))
-		self.writer.endMethodBody()
-		self.writer.endMethod()
-		 
-	def visit_ExitAction(self, exit_method):
-		exited_node = exit_method.parent_node
-		self.writer.beginMethod("exit_" + exited_node.full_name)
-		self.writer.beginMethodBody()
-
-		#If the exited node is composite take care of potential history and the leaving of descendants
-		if exited_node.is_composite :
-			#handle history
-			if exited_node.save_state_on_exit :
-				self.writer.addAssignment(
-					GLC.MapIndexedExpression(
-						GLC.SelfProperty("history_state"),
-						GLC.SelfProperty(exited_node.full_name)),
-					GLC.MapIndexedExpression(
-						GLC.SelfProperty("current_state"),
-						GLC.SelfProperty(exited_node.full_name)))
-			
-			#Take care of leaving children
-			children = exited_node.children
-			if exited_node.is_parallel_state:
-				for child in children:
-					if not child.is_history :
-						self.writer.add(GLC.FunctionCall(GLC.SelfProperty("exit_"+child.full_name)))
-			else:
-				for child in children:
-					if not child.is_history :
-						self.writer.beginIf(GLC.ArrayContains(
-								GLC.MapIndexedExpression(
-									GLC.SelfProperty("current_state"),
-									GLC.SelfProperty(exited_node.full_name)),
-								GLC.SelfProperty(child.full_name)))
-						self.writer.add(GLC.FunctionCall(GLC.SelfProperty("exit_"+child.full_name)))
-						self.writer.endIf()
-		
-		# take care of any AFTER events
-		for transition in exited_node.transitions :
-			trigger = transition.getTrigger()
-			if trigger.isAfter() :
-				self.writer.add(GLC.MapRemoveElement(
-					GLC.SelfProperty("timers"),
-					str(trigger.getAfterIndex())))
-				
-		#Execute user-defined exit action if present
-		if exit_method.action:
-			exit_method.action.accept(self)
-			
-		#Adjust state
-		self.writer.addAssignment(
-			GLC.MapIndexedExpression(
-				GLC.SelfProperty("current_state"),
-				GLC.SelfProperty(exited_node.parent.full_name)),
-			GLC.ArrayExpression()) # SPECIAL CASE FOR ORTHOGONAL??
-		
-		self.writer.endMethodBody()
-		self.writer.endMethod()
-		
-			
-	#helper method
-	def writeEnterHistory(self, entered_node, is_deep):
-		self.writer.beginMethod("enterHistory" + ("Deep" if is_deep else "Shallow") + "_" + entered_node.full_name)
-		self.writer.beginMethodBody()
-
-		self.writer.beginIf(GLC.EqualsExpression(
-			GLC.ArrayLength(
-				GLC.MapIndexedExpression(
-					GLC.SelfProperty("history_state"),
-					GLC.SelfProperty(entered_node.full_name))),
-			"0"))
-		"""self.writer.beginIfBlock(GLC.EqualsExpression(
-			GLC.ArrayLength(
-				GLC.MapIndexedExpression(
-					GLC.SelfProperty("history_state"),
-					GLC.SelfProperty(entered_node.full_name))),
-			"0"))"""
-		defaults = entered_node.defaults
-
-		for node in defaults:
-			if node.is_basic :
-				self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_"+node.full_name)))
-			elif node.is_composite :
-				self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterDefault_"+node.full_name)))
-
-		self.writer.endIf()
-		self.writer.beginElse()
-		children = entered_node.children
-		if entered_node.is_parallel_state:
-			for child in children:
-				if not child.is_history :
-					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_"+child.full_name)))
-					self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterHistory"+("Deep" if is_deep else "Shallow")+"_"+child.full_name)))
-		else:
-			for child in children:
-				if not child.is_history :
-					self.writer.beginIf(GLC.ArrayContains(
-						GLC.MapIndexedExpression(
-							GLC.SelfProperty("history_state"),
-							GLC.SelfProperty(entered_node.full_name)),
-						GLC.SelfProperty(child.full_name)))
-					if child.is_composite:
-						if is_deep :
-							self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_"+child.full_name)))
-							self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterHistoryDeep_"+child.full_name)))
-						else :
-							self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enterDefault_"+child.full_name)))
-					else:
-						self.writer.add(GLC.FunctionCall(GLC.SelfProperty("enter_"+child.full_name)))
-					self.writer.endIf()
-		self.writer.endElse()
-
-		self.writer.endMethodBody()
-		self.writer.endMethod()
-
-	def visit_StateChart(self, statechart):
-
-		# assign each node a unique ID
-		self.writer.addVSpace()
-		self.writer.addComment("Unique IDs for all statechart nodes")
-		for (i,node) in enumerate(statechart.composites + statechart.basics):
-			self.writer.addStaticAttribute(node.full_name, str(i))
-
-
-
-		self.writer.addVSpace()
-		self.writer.addComment("Statechart enter/exit action method(s)")
-		
-		#visit enter and exit action of children
-		for i in statechart.composites + statechart.basics:
-			if i is not statechart.root :
-				i.enter_action.accept(self)
-				i.exit_action.accept(self)
-
-		# write out statecharts methods for enter/exit state
-		if len(statechart.composites) > 1 :
-			self.writer.addVSpace()
-			self.writer.addComment("Statechart enter/exit default method(s)")
-			for i in statechart.composites :
-				if i is not statechart.root :
-					self.writeEnterDefault(i)
-
-		# write out statecharts methods for enter/exit history
-		if statechart.histories:
-			self.writer.addVSpace()
-			self.writer.addComment("Statechart enter/exit history method(s)")
-			for i in statechart.shallow_history_parents:
-				self.writeEnterHistory(i, False)
-			for i in statechart.deep_history_parents:
-				self.writeEnterHistory(i, True) 
-
-		self.writer.addVSpace()
-		self.writer.addComment("Statechart transitions")
-		self.writeTransitionsRecursively(statechart.root)			
-				
-		# write out transition function
-		self.writer.beginMethod("generateCandidates", "Generate transition candidates for current small step")
-		self.writer.beginMethodBody()
-		self.writer.add(GLC.FunctionCall(
-				GLC.SelfProperty("generateCandidates_"+statechart.root.full_name)))
-		self.writer.endMethodBody()
-		self.writer.endMethod()
-
-	def visit_SelfReference(self, self_reference):
-		self.writer.add(GLC.SelfExpression())
-
-	def visit_StateReference(self, state_ref):
-		self.writer.beginArray()
-		for node in state_ref.getNodes():
-			self.writer.add(GLC.SelfProperty(node.full_name))
-		self.writer.endArray()
-
-	def visit_InStateCall(self, in_state_call):
-		self.writer.beginFunctionCall(GLC.SelfProperty("inState"))
-		self.writer.startRecordingExpression()
-		in_state_call.target.accept(self)
-		expr = self.writer.stopRecordingExpression()
-		self.writer.addActualParameter(expr)
-		self.writer.endFunctionCall()
-
-	def visit_Expression(self, expression):
-		self.writer.startRecordingExpression()
-		self.writer.beginGlue()
-		for part in expression.expression_parts:
-			part.accept(self)
-		self.writer.endGlue()
-		expr = self.writer.stopRecordingExpression()
-		self.writer.add(expr)
-
-	def visit_ExpressionPartString(self, e):
-		self.writer.add(e.string)
-		
-	def visit_RaiseEvent(self, raise_event):
-		self.writer.startRecordingExpression()
-		self.writer.begin(GLC.NewExpression("Event"))
-
-		self.writer.addActualParameter(GLC.String(raise_event.getEventName()))
-		if raise_event.isOutput():
-			self.writer.addActualParameter(GLC.String(raise_event.getPort()))
-		else:
-			self.writer.addActualParameter(GLC.NoneExpression())
-
-		self.writer.end()
-		new_event_expr = self.writer.stopRecordingExpression()
-
-		self.writer.startRecordingExpression()
-		self.writer.beginArray()
-		if raise_event.isCD():
-			self.writer.add(GLC.SelfExpression())
-		for param in raise_event.getParameters() :
-			param.accept(self) # -> visit_Expression will cause expressions to be added to array
-		self.writer.endArray()
-		parameters_array_expr = self.writer.stopRecordingExpression()
-		new_event_expr.getActualParameters().add(parameters_array_expr)
-
-		if raise_event.isNarrow():
-			self.writer.add(GLC.FunctionCall(
-				GLC.Property(GLC.SelfProperty("big_step"), "outputEventOM"), [
-					GLC.NewExpression("Event", [
-						GLC.String("narrow_cast"),
-						GLC.NoneExpression(),
-						GLC.ArrayExpression([
-							GLC.SelfExpression(),
-							raise_event.getTarget(),
-							new_event_expr])])]))
-		elif raise_event.isLocal():
-			self.writer.add(GLC.FunctionCall(
-				GLC.SelfProperty("raiseInternalEvent"),
-				[new_event_expr]))
-		elif raise_event.isOutput():
-			self.writer.add(GLC.FunctionCall(
-				GLC.Property(GLC.SelfProperty("big_step"), "outputEvent"),
-				[new_event_expr]))
-		elif raise_event.isCD():
-			self.writer.add(GLC.FunctionCall(
-				GLC.Property(GLC.SelfProperty("big_step"), "outputEventOM"),
-				[new_event_expr]))
-		elif raise_event.isBroad():
-			self.writer.add(GLC.FunctionCall(
-				GLC.Property(GLC.SelfProperty("big_step"), "outputEventOM"),
-				[GLC.NewExpression("Event", [
-					GLC.String("broad_cast"),
-					GLC.NoneExpression(),
-					GLC.ArrayExpression([
-						new_event_expr])])]))
-			
-	def visit_Script(self, script):
-		self.writer.addRawCode(script.code)
-		
-	def visit_Log(self, log):
-		self.writer.add(GLC.LogStatement(log.message))
-		
-	def visit_Assign(self, assign):
-		self.writer.startRecordingExpression()
-		assign.lvalue.accept(self) # --> visit_Expression
-		lvalue = self.writer.stopRecordingExpression()
-		self.writer.startRecordingExpression()
-		assign.expression.accept(self) # --> visit_Expression
-		rvalue = self.writer.stopRecordingExpression()
-		self.writer.addAssignment(lvalue, rvalue)
-

+ 0 - 996
kernel/mvk_server/python_sccd_compiler/generic_language_constructs.py

@@ -1,996 +0,0 @@
-import abc
-from visitor import Visitor, Visitable
-
-
-class GenericConstruct(Visitable):
-	__metaclass__ = abc.ABCMeta
-
-
-# base class for constructs that are a collection of other constructs
-class AbstractList:
-	__metaclass__ = abc.ABCMeta
-
-	@abc.abstractmethod
-	def add(self, generic_construct):
-		pass
-
-
-class BlockEntry(GenericConstruct):
-	__metaclass__ = abc.ABCMeta
-
-	@abc.abstractmethod
-	def isEmpty(self):
-		pass
-
-
-class DeclarationBase:
-	def __init__(self, identifier, description = None):
-		self.identifier = identifier
-		self.description = description # string describing declared artifact
-
-	def getIdentifier(self):
-		return self.identifier
-
-	def getDescription(self):
-		return self.description
-
-
-class Statement(BlockEntry):
-	pass
-
-
-class Package(Statement, AbstractList, DeclarationBase):
-	def __init__(self, identifier, description = None):
-		DeclarationBase.__init__(self, identifier, description)
-		self.declarations = []
-
-	def add(self, item):
-		self.declarations.append(MakeDeclaration(item))
-
-	def getDeclarations(self):
-		return self.declarations
-
-	def isEmpty(self):
-		return False
-
-
-class FormalParameters(GenericConstruct, AbstractList):
-	def __init__(self, parameter_list = None):
-		if parameter_list is None: parameter_list = []
-		self.parameter_list = parameter_list
-
-	def add(self, parameter):
-		self.parameter_list.append(parameter)
-
-	def getParameterList(self):
-		return self.parameter_list
-
-class AST(GenericConstruct, AbstractList):
-	def __init__(self):
-		self.entries = []
-
-	def add(self, entry):
-		self.entries.append(MakeBlockEntry(entry))
-
-	def getEntries(self):
-		return self.entries
-
-
-class Block(AST):
-	def __init__(self):
-		AST.__init__(self)
-
-	def isEmpty(self):
-		for e in self.getEntries():
-			if not e.isEmpty():
-				return False
-		return True
-
-
-class ForLoopBody(Block):
-	def __init__(self, for_loop):
-		Block.__init__(self)
-		self.for_loop = for_loop
-
-	def getForLoop(self):
-		return self.for_loop
-
-
-class MethodBody(Block):
-	def __init__(self, method):
-		Block.__init__(self)
-		self.method = method
-
-	def getMethod(self):
-		return self.method
-
-
-#class ConstructorBody(MethodBody):
-#	def __init__(self, method):
-#		MethodBody.__init__(self, method)
-
-#class DestructorBody(MethodBody):
-#	def __init__(self, method):
-#		MethodBody.__init__(self, method)
-
-
-class ClassMember(GenericConstruct, DeclarationBase):
-	def __init__(self, c, identifier, description = None):
-		DeclarationBase.__init__(self, identifier, description)
-		self.c = c # Class
-
-	def getClass(self):
-		return self.c
-
-
-class MethodBase(ClassMember):
-	def __init__(self, c, identifier, description = None):
-		ClassMember.__init__(self, c, identifier, description)
-		self.formal_parameters = FormalParameters()
-		self.body = MethodBody(self)
-
-	def getBody(self):
-		return self.body
-
-	def getFormalParameters(self):
-		return self.formal_parameters
-
-
-class Method(MethodBase):
-	def __init__(self, c, identifier, description = None):
-		MethodBase.__init__(self, c, identifier, description)
-
-
-class Constructor(MethodBase):
-	def __init__(self, c, description = None):
-		MethodBase.__init__(self, c, None, description)
-
-
-class Destructor(MethodBase):
-	def __init__(self, c, description = None):
-		MethodBase.__init__(self, c, None, description)
-
-
-class Class(GenericConstruct, AbstractList, DeclarationBase):
-	def __init__(self, identifier, super_class_identifier_list = None, description = None):
-		DeclarationBase.__init__(self, identifier, description)
-		self.super_class_identifier_list = super_class_identifier_list # string
-		self.constructor = Constructor(self)
-		self.destructor = Destructor(self)
-		self.members = []
-
-	def getSuperClassIdentifierList(self):
-		return self.super_class_identifier_list
-
-	def getConstructor(self):
-		return self.constructor
-
-	def getDestructor(self):
-		return self.destructor
-
-	def add(self, class_member):
-		self.members.append(class_member)
-
-	def getMembers(self):
-		return self.members
-
-
-class AttributeBase(ClassMember):
-	def __init__(self, c, identifier, init_value = None):
-		ClassMember.__init__(self, c, identifier)
-		self.init_value = MakeExpression(init_value)
-
-	def getInitValue(self):
-		return self.init_value
-
-
-class Attribute(AttributeBase):
-	def __init__(self, c, identifier, init_value = None):
-		AttributeBase.__init__(self, c, identifier, init_value)
-
-
-class StaticAttribute(AttributeBase):
-	def __init__(self, c, name, init_value = None):
-		AttributeBase.__init__(self, c, name, init_value)
-
-
-class FormalParameter(GenericConstruct, DeclarationBase):
-	def __init__(self, identifier, default_value = None, description = None):
-		DeclarationBase.__init__(self, identifier, description)
-		#self.identifier = identifier
-		self.default_value = MakeExpression(default_value)
-
-	def getDefaultValue(self):
-		return self.default_value
-
-
-class IncludeStatement(Statement):
-	def __init__(self, module_path, imported_symbols = None):
-		if imported_symbols is None: imported_symbols = []
-		self.module_path = MakeExpressionList(module_path) # list of modules
-		self.imported_symbols = imported_symbols
-
-	def getModulePath(self):
-		return self.module_path
-
-	def getImportedSymbols(self):
-		return self.imported_symbols
-
-	def isEmpty(self):
-		return False
-
-
-class ReturnStatement(Statement):
-	def __init__(self, expr):
-		self.expr = MakeExpression(expr)
-
-	def getExpression(self):
-		return self.expr
-
-	def isEmpty(self):
-		return False
-
-class BreakStatement(Statement):
-	def isEmpty(self):
-		return False	
-
-class ThrowExceptionStatement(Statement):
-	def __init__(self, expr):
-		self.expr = MakeExpression(expr)
-
-	def getExpression(self):
-		return self.expr
-
-	def isEmpty(self):
-		return False
-
-
-class VSpace(BlockEntry):
-	def isEmpty(self):
-		return True
-
-
-class CommentBase(BlockEntry):
-	def __init__(self, text):
-		self.text = text
-
-	def isEmpty(self):
-		return True
-
-	def getText(self):
-		return self.text
-
-
-class SingleLineComment(CommentBase):
-	def __init__(self, text):
-		CommentBase.__init__(self,text)
-
-
-class MultiLineComment(CommentBase):
-	def __init__(self, text):
-		CommentBase.__init__(self,text)
-
-
-class ConditionalStatementBase(Statement, AbstractList):
-	def __init__(self, body = None):
-		if body is None: body = Block()
-		self.body = body
-
-	def add(self, stmt):
-		self.body.add(stmt)
-
-	def getBody(self):
-		return self.body
-
-	def isEmpty(self):
-		return False
-
-
-class IfStatement(ConditionalStatementBase):
-	def __init__(self, condition):
-		ConditionalStatementBase.__init__(self)
-		self.condition = MakeExpression(condition)
-
-	def getCondition(self):
-		return self.condition
-
-
-class ElseStatement(ConditionalStatementBase):
-	def __init__(self):
-		ConditionalStatementBase.__init__(self)
-
-
-class ElseIfStatement(IfStatement):
-	def __init__(self, condition, is_first = False):
-		IfStatement.__init__(self, condition)
-		self.is_first = is_first
-
-	# in a series of ElseIfStatements, the first ElseIfStatement will be a normal if statement
-	def isFirst(self):
-		return self.is_first
-
-
-class ForLoopIterateBase(ConditionalStatementBase):
-	def __init__(self, collection_expr, iterator_identifier):
-		ConditionalStatementBase.__init__(self, ForLoopBody(self))
-		self.collection_expr = MakeExpression(collection_expr)
-		self.iterator_identifier = iterator_identifier
-
-	def getCollectionExpression(self):
-		return self.collection_expr
-
-	def getIteratorIdentifier(self):
-		return self.iterator_identifier
-
-
-class ForLoopIterateArray(ForLoopIterateBase):
-	def __init__(self, array_expr, iterator_identifier):
-		ForLoopIterateBase.__init__(self, array_expr, iterator_identifier)
-
-
-class ForLoopIterateMapValues(ForLoopIterateBase):
-	def __init__(self, map_expr, iterator_identifier):
-		ForLoopIterateBase.__init__(self, map_expr, iterator_identifier)
-
-
-class ExpressionStatement(Statement):
-	def __init__(self, expression):
-		self.expression = expression
-
-	def getExpression(self):
-		return self.expression
-
-	def isEmpty(self):
-		return False
-
-
-# block of raw code
-class RawCode(BlockEntry):
-	def __init__(self, text):
-		self.text = text
-
-	def getText(self):
-		return self.text
-
-	def isEmpty(self):
-		return (len(self.text.strip()) == 0)
-
-
-# log message to console
-class LogStatement(Statement):
-	def __init__(self, msg):
-		self.msg = msg
-
-	def getMessage(self):
-		return self.msg
-
-	def isEmpty(self):
-		return False
-
-
-class Expression(GenericConstruct):
-	__metaclass__ = abc.ABCMeta
-
-	@abc.abstractmethod
-	def isCompound(self):
-		pass
-
-class SimpleExpression(Expression):
-	def isCompound(self):
-		return False
-
-class CompoundExpression(Expression):
-	def isCompound(self):
-		return True
-
-class RuntimeModuleIdentifier(SimpleExpression):
-	pass
-
-# Not a real language construct, simply 'glues' expressions together.
-class Glue(SimpleExpression, AbstractList):
-	def __init__(self):
-		self.expression_list = []
-
-	def add(self, expr):
-		self.expression_list.append(MakeExpression(expr))
-
-	def getExpressionList(self):
-		return self.expression_list
-
-
-class ForLoopCurrentElement(SimpleExpression):
-	def __init__(self, collection_expr, iterator_identifier):
-		self.collection_expr = MakeExpression(collection_expr)
-		self.iterator_identifier = iterator_identifier
-
-	def getCollectionExpression(self):
-		return self.collection_expr
-
-	def getIteratorIdentifier(self):
-		return self.iterator_identifier
-
-
-class Literal(SimpleExpression):
-	def __init__(self, text):
-		self.text = text
-
-	def getText(self):
-		return self.text
-
-
-class String(Literal):
-	def __init__(self, text):
-		Literal.__init__(self, text)
-
-
-class Property(SimpleExpression):
-	def __init__(self, owner, prop):
-		self.owner = MakeExpression(owner)
-		self.prop = prop
-
-	def getOwnerExpression(self):
-		return self.owner
-
-	def getProperty(self):
-		return self.prop
-
-
-class MapIndexedExpression(SimpleExpression):
-	def __init__(self, map_expr, key_expr):
-		self.map_expr = MakeExpression(map_expr)
-		self.key_expr = MakeExpression(key_expr)
-
-	def getMapExpression(self):
-		return self.map_expr
-
-	def getKeyExpression(self):
-		return self.key_expr
-
-
-class ArrayIndexedExpression(SimpleExpression):
-	def __init__(self, array_expr, index_expr):
-		self.array_expr = MakeExpression(array_expr)
-		self.index_expr = MakeExpression(index_expr)
-
-	def getArrayExpression(self):
-		return self.array_expr
-
-	def getIndexExpression(self):
-		return self.index_expr
-
-
-class ActualParameters(GenericConstruct, AbstractList):
-	def __init__(self, parameter_list = None):
-		if parameter_list is None: parameter_list = []
-		self.parameter_list = MakeExpressionList(parameter_list)
-
-	def add(self, p):
-		self.parameter_list.append(MakeExpression(p))
-		pass
-
-	def getParameterList(self):
-		return self.parameter_list
-
-
-class FunctionCallBase(SimpleExpression):
-	def __init__(self, actual_parameters = None):
-		if actual_parameters is None: actual_parameters = ActualParameters()
-		self.actual_parameters = MakeActualParameters(actual_parameters)
-
-	def getActualParameters(self):
-		return self.actual_parameters
-	
-
-
-class FunctionCall(FunctionCallBase):
-	def __init__(self, function_expr, actual_parameters = None):
-		FunctionCallBase.__init__(self, actual_parameters)
-		self.function_expr = MakeExpression(function_expr)
-
-	def getFunctionExpression(self):
-		return self.function_expr
-
-
-class SuperClassCallBase(FunctionCallBase):
-	def __init__(self, super_class_identifier, actual_parameters = None):
-		FunctionCallBase.__init__(self, actual_parameters)
-		self.super_class_identifier = super_class_identifier
-
-	def getSuperClassIdentifier(self):
-		return self.super_class_identifier
-
-
-class SuperClassConstructorCall(SuperClassCallBase):
-	def __init__(self, super_class_identifier, actual_parameters = None):
-		SuperClassCallBase.__init__(self, super_class_identifier, actual_parameters)
-
-
-class SuperClassDestructorCall(SuperClassCallBase):
-	def __init__(self, super_class_identifier):
-		SuperClassCallBase.__init__(self, super_class_identifier)
-
-
-class SuperClassMethodCall(SuperClassCallBase):
-	def __init__(self, super_class_identifier, method_identifier, actual_parameters = None):
-		SuperClassCallBase.__init__(self, super_class_identifier, actual_parameters)
-		self.method_identifier = method_identifier
-
-	def getMethodIdentifier(self):
-		return self.method_identifier
-
-
-class NewExpression(FunctionCallBase):
-	def __init__(self, type_expr, actual_parameters = None):
-		FunctionCallBase.__init__(self, actual_parameters)
-		self.type_expr = MakeExpression(type_expr)
-
-	def getTypeExpression(self):
-		return self.type_expr
-
-
-class SelfExpression(SimpleExpression):
-	pass
-
-
-class SelfProperty(Property):
-	def __init__(self, prop):
-		Property.__init__(self, SelfExpression(), prop)
-
-
-class Operator(GenericConstruct):
-	pass
-
-
-class AndOperator(Operator):
-	pass
-
-class OrOperator(Operator):
-	pass
-
-class LessThanOperator(Operator):
-	pass
-
-class GreaterThanOperator(Operator):
-	pass
-
-class NotOperator(Operator):
-	pass
-
-class EqualsOperator(Operator):
-	pass
-
-class AssignmentOperator(Operator):
-	pass
-
-class ProductOperator(Operator):
-	pass
-
-
-class UnaryExpression(CompoundExpression):
-	def __init__(self, operator, expr):
-		self.operator = operator
-		self.expr = MakeExpression(expr)
-
-	def getExpression(self):
-		return self.expr
-
-	def getOperator(self):
-		return self.operator
-
-
-class BinaryExpression(CompoundExpression):
-	def __init__(self, lhs_expr, operator, rhs_expr):
-		self.lhs_expr = MakeExpression(lhs_expr)
-		self.operator = operator
-		self.rhs_expr = MakeExpression(rhs_expr)
-
-	def getLhsExpression(self):
-		return self.lhs_expr
-
-	def getRhsExpression(self):
-		return self.rhs_expr
-
-	def getOperator(self):
-		return self.operator
-
-
-class NotExpression(UnaryExpression):
-	def __init__(self, expr):
-		UnaryExpression.__init__(self, NotOperator(), expr)
-
-class AndExpression(BinaryExpression):
-	def __init__(self, lexpr = None, rexpr = None):
-		BinaryExpression.__init__(self, lexpr, AndOperator(), rexpr)
-
-class OrExpression(BinaryExpression):
-	def __init__(self, lexpr = None, rexpr = None):
-		BinaryExpression.__init__(self, lexpr, OrOperator(), rexpr)
-
-class LessThanExpression(BinaryExpression):
-	def __init__(self, lexpr = None, rexpr = None):
-		BinaryExpression.__init__(self, lexpr, LessThanOperator(), rexpr)
-
-class GreaterThanExpression(BinaryExpression):
-	def __init__(self, lexpr = None, rexpr = None):
-		BinaryExpression.__init__(self, lexpr, GreaterThanOperator(), rexpr)
-
-class EqualsExpression(BinaryExpression):
-	def __init__(self, lexpr = None, rexpr = None):
-		BinaryExpression.__init__(self, lexpr, EqualsOperator(), rexpr)
-
-class AssignmentExpression(BinaryExpression):
-	def __init__(self, lexpr = None, rexpr = None):
-		BinaryExpression.__init__(self, lexpr, AssignmentOperator(), rexpr)
-
-class ProductExpression(BinaryExpression):
-	def __init__(self, lexpr = None, rexpr = None):
-		BinaryExpression.__init__(self, lexpr, ProductOperator(), rexpr)
-
-
-class FalseExpression(SimpleExpression):
-	pass
-
-class TrueExpression(SimpleExpression):
-	pass
-
-
-class LocalVariableDeclaration(Expression, DeclarationBase):
-	def __init__(self, identifier, init_value = None, description = None):
-		DeclarationBase.__init__(self, identifier, description)
-		self.init_value = MakeExpression(init_value)
-
-	def getInitValue(self):
-		self.init_value
-
-	def isCompound(self):
-		return (self.init_value != None)
-
-
-class MapExpression(SimpleExpression):
-	def __init__(self, elements = None):
-		if elements is None: elements = {}
-		self.elements = MakeExpressionMap(elements)
-
-	def getElements(self):
-		return self.elements
-
-class MapRemoveElement(Statement):
-	def __init__(self, map_expr, key_expr):
-		self.map_expr = MakeExpression(map_expr)
-		self.key_expr = MakeExpression(key_expr)
-
-	def getMapExpression(self):
-		return self.map_expr
-
-	def getKeyExpression(self):
-		return self.key_expr
-
-	def isEmpty(self):
-		return False
-
-
-class ArrayExpression(SimpleExpression, AbstractList):
-	def __init__(self, elements = None):
-		if elements is None: elements = []
-		self.elements = MakeExpressionList(elements)
-
-	def add(self, element):
-		self.elements.append(MakeExpression(element))
-
-	def getElements(self):
-		return self.elements
-
-
-class ArrayLength(SimpleExpression):
-	def __init__(self, array_expr):
-		self.array_expr = MakeExpression(array_expr)
-
-	def getArrayExpression(self):
-		return self.array_expr
-
-
-class ArrayElementOperation(Expression):
-	def __init__(self, array_expr, elem_expr):
-		self.array_expr = MakeExpression(array_expr)
-		self.elem_expr = MakeExpression(elem_expr)
-
-	def getArrayExpression(self):
-		return self.array_expr
-
-	def getElementExpression(self):
-		return self.elem_expr
-
-class ArrayIndexOf(ArrayElementOperation, SimpleExpression):
-	def __init__(self, array_expr, elem_expr):
-		ArrayElementOperation.__init__(self, array_expr, elem_expr)
-
-class ArrayContains(ArrayElementOperation, CompoundExpression):
-	def __init__(self, array_expr, elem_expr):
-		ArrayElementOperation.__init__(self, array_expr, elem_expr)
-
-class ArrayPushBack(ArrayElementOperation, SimpleExpression):
-	def __init__(self, array_expr, elem_expr):
-		ArrayElementOperation.__init__(self, array_expr, elem_expr)
-
-
-class NoneExpression(SimpleExpression):
-	pass
-
-
-# helpers
-
-def MakeExpression(expr):
-
-	try:
-		bs = basestring
-	except NameError:
-		bs = str
-
-	if isinstance(expr, Expression):
-		return expr
-	elif isinstance(expr, bs):
-		return Literal(expr)
-	elif expr is None:
-		return None
-	else:
-		raise Exception("Can't turn argument of type '" + str(type(expr)) + "' into Expression.")
-
-def MakeExpressionList(l):
-	if not isinstance(l, list):
-		raise Exception("Expected argument of type 'list'.")
-	for i in range(len(l)):
-		l[i] = MakeExpression(l[i])
-	return l
-
-def MakeExpressionMap(m):
-	if not isinstance(m, dict):
-		raise Exception("Expected argument of type 'dict'.")
-	for key in list(m.keys()):
-		m[key] = MakeExpression(m[key])
-	return m
-
-def MakeBlockEntry(stmt):
-	if isinstance(stmt, BlockEntry):
-		return stmt
-	elif isinstance(stmt, Expression):
-		return ExpressionStatement(stmt)
-	elif stmt is None:
-		return None
-	else:
-		raise Exception("Can't turn argument of type '" + str(type(stmt)) + "' into BlockEntry.")
-
-def MakeDeclaration(obj):
-	if isinstance(obj, DeclarationBase):
-		return obj
-	else:
-		raise Exception("Can't turn argument of type '" + str(type(stmt)) + "' into DeclarationBase.")
-
-def MakeActualParameters(obj):
-	if isinstance(obj, ActualParameters):
-		return obj
-	elif isinstance (obj, list):
-		return ActualParameters(obj)
-	else:
-		raise Exception("Can't turn argument of type '" + str(type(obj)) + "' into ActualParameters.")
-
-"""def MakeFormalParameter(parameter, default_value):
-	if isinstance(parameter, FormalParameter):
-		return parameter
-	elif default_value:
-		return FormalParameter(parameter, default_value)
-	else:
-		return FormalParameter(parameter)"""
-
-
-class GenericWriterBase(Visitor):
-	__metaclass__ = abc.ABCMeta
-
-	# overrides Visitor.generic_visit
-	def generic_visit(self, node):
-		raise Exception("Writer has no visit method for node of type '" + str(type(node)) + "'.")
-
-	#### HELPERS ####
-
-	def writeAll(self, l):
-		for item in l:
-			item.accept(self)
-
-	def writeTuple(self, obj):
-		self.out.extendWrite("(")
-		self.writeCommaSeparated(obj)
-		self.out.extendWrite(")")
-
-	@abc.abstractmethod
-	def writeComment(self, text):
-		pass
-
-	@abc.abstractmethod
-	def writeMultiLineComment(self, text):
-		pass
-
-	def writeCommaSeparated(self, l):
-		for i in range(len(l)):
-			if i != 0:
-				self.out.extendWrite(", ")
-			l[i].accept(self)
-
-	def writeDescription(self, decl):
-		description = decl.getDescription()
-		if description:
-			self.writeComment(description)
-
-	def writeCompoundExpr(self, expr):
-		if expr.isCompound():
-			self.out.extendWrite("(")
-		expr.accept(self)
-		if expr.isCompound():
-			self.out.extendWrite(")")
-
-	#### VISIT METHODS BASE IMPLEMENTATIONS ####
-
-	def visit_ArrayIndexedExpression(self, i):
-		a = i.getArrayExpression()
-		index = i.getIndexExpression()
-
-		a.accept(self)
-		self.out.extendWrite("[")
-		index.accept(self)
-		self.out.extendWrite("]")
-
-	def visit_ActualParameters(self, p):
-		self.writeTuple(p.getParameterList())
-
-	def visit_AssignmentOperator(self, assign):
-		self.out.extendWrite(" = ")
-
-	def visit_BinaryExpression(self, b):
-		lhs = b.getLhsExpression()
-		rhs = b.getRhsExpression()
-		op = b.getOperator()
-
-		self.writeCompoundExpr(lhs)
-		op.accept(self)
-		self.writeCompoundExpr(rhs)
-
-	def visit_FormalParameters(self, p):
-		self.writeTuple(p.getParameterList())
-
-	def visit_FunctionCall(self, f):
-		func = f.getFunctionExpression()
-		params = f.getActualParameters()
-
-		func.accept(self)
-		params.accept(self)
-
-	def visit_Glue(self, g):
-		self.writeAll(g.getExpressionList())
-
-	def visit_GreaterThanOperator(self, g):
-		self.out.extendWrite(" > ")
-
-	def visit_LessThanOperator(self, l):
-		self.out.extendWrite(" < ")
-
-	def visit_Literal(self, l):
-		self.out.extendWrite(l.getText())
-
-	def visit_MultiLineComment(self, c):
-		self.writeMultiLineComment(c.getText())
-
-	def visit_ProductOperator(self, p):
-		self.out.extendWrite(" * ")
-
-	def visit_Property(self, p):
-		owner = p.getOwnerExpression()
-		prop = p.getProperty()
-
-		owner.accept(self)
-		self.out.extendWrite("." + prop)
-
-	def visit_RawCode(self, c):
-		self.out.writeCodeCorrectIndent(c.getText())
-
-	def visit_SingleLineComment(self, comment):
-		self.writeComment(comment.getText())
-
-	def visit_String(self, string):
-		self.out.extendWrite("\"" + string.getText().replace("\"", "\\\"") + "\"")
-
-	def visit_UnaryExpression(self, u):
-		expr = u.getExpression()
-		op = u.getOperator()
-
-		op.accept(self)
-		self.writeCompoundExpr(expr)
-
-	def visit_VSpace(self, v):
-		self.out.write()
-
-
-class CLikeWriterBase(GenericWriterBase):
-
-	### HELPERS ###
-
-	def writeComment(self, text):
-		self.out.write("// " + text)
-
-	def writeMultiLineComment(self, text):
-		self.out.write("/* " + text + "*/")
-
-	### VISIT METHODS ###
-
-	def visit_AndOperator(self, a):
-		self.out.extendWrite(" && ")
-
-	def visit_Block(self, b):
-		self.out.extendWrite(" {")
-		self.out.indent()
-		self.writeAll(b.getEntries())
-		self.out.dedent()
-		self.out.write("}")
-
-	def visit_BreakStatement(self, b):
-		self.out.write("break;")
-
-	def visit_ElseStatement(self, else_stmt):
-		self.out.extendWrite(" else ")
-		else_stmt.getBody().accept(self)
-
-	def visit_ElseIfStatement(self, else_if):
-		condition = else_if.getCondition()
-		body = else_if.getBody()
-
-		if else_if.isFirst():
-			self.out.write("if (")
-		else:
-			self.out.extendWrite(" else if (")
-		condition.accept(self)
-		self.out.extendWrite(")")
-		body.accept(self)
-
-	def visit_EqualsOperator(self, e):
-		self.out.extendWrite(" == ")
-
-	def visit_ExpressionStatement(self, stmt):
-		self.out.write() # expressions never begin with a newline
-		stmt.getExpression().accept(self)
-		self.out.extendWrite(";")
-
-	def visit_FalseExpression(self, f):
-		self.out.extendWrite("false")
-
-	def visit_IfStatement(self, if_stmt):
-		condition = if_stmt.getCondition()
-		body = if_stmt.getBody()
-
-		self.out.write("if (")
-		condition.accept(self)
-		self.out.extendWrite(")")
-		body.accept(self)
-
-	def visit_NewExpression(self, new):
-		type_expr = new.getTypeExpression()
-		params = new.getActualParameters()
-
-		self.out.extendWrite("new ")
-		type_expr.accept(self)
-		params.accept(self)
-
-	def visit_NotOperator(self, n):
-		self.out.extendWrite("!")
-
-	def visit_OrOperator(self, o):
-		self.out.extendWrite(" || ")
-
-	def visit_ReturnStatement(self, r):
-		self.out.write("return ")
-		r.getExpression().accept(self)
-		self.out.extendWrite(";")
-
-	def visit_SelfExpression(self, s):
-		self.out.extendWrite("this")
-
-	def visit_TrueExpression(self, t):
-		self.out.extendWrite("true")
-
-

+ 0 - 285
kernel/mvk_server/python_sccd_compiler/javascript_writer.py

@@ -1,285 +0,0 @@
-from kernel.mvk_server.python_sccd_compiler.visitor import Visitor
-from kernel.mvk_server.python_sccd_compiler.generic_language_constructs import *
-
-class JavascriptWriter(CLikeWriterBase):
-	def __init__(self, outputter):
-		self.out = outputter
-
-	### VISIT METHODS ###
-
-	def visit_ArrayContains(self, a):
-		array = a.getArrayExpression()
-		el = a.getElementExpression()
-
-		self.out.extendWrite("(")
-		array.accept(self)
-		self.out.extendWrite(".indexOf(")
-		el.accept(self)
-		self.out.extendWrite(") !== -1)")
-
-	def visit_ArrayExpression(self, a):
-		elements = a.getElements()
-		if len(elements) == 0:
-			self.out.extendWrite("new Array()")
-		else:
-			self.out.extendWrite("[")
-			self.writeCommaSeparated(elements)
-			self.out.extendWrite("]")
-
-	def visit_ArrayIndexOf(self, a):
-		array = a.getArrayExpression()
-		el = a.getElementExpression()
-
-		array.accept(self)
-		self.out.extendWrite(".indexOf(")
-		el.accept(self)
-		self.out.extendWrite(")")
-
-	def visit_ArrayLength(self, a):
-		a.getArrayExpression().accept(self)
-		self.out.extendWrite(".length")
-
-	def visit_ArrayPushBack(self, a):
-		array = a.getArrayExpression()
-		el = a.getElementExpression()
-
-		array.accept(self)
-		self.out.extendWrite(".push(")
-		el.accept(self)
-		self.out.extendWrite(")")
-
-	def visit_AST(self, ast):
-		self.writeAll(ast.getEntries())
-
-	def visit_Class(self, c):
-		class_name = c.getIdentifier()
-		constructor = c.getConstructor()
-		super_classes = c.getSuperClassIdentifierList()
-		description = c.getDescription()
-
-		self.out.write()
-		if description:
-			self.writeComment(description)
-		constructor.accept(self)
-		if super_classes:
-			self.out.write(class_name + ".prototype = new Object();")
-			self.out.write("(function() {")
-			self.out.indent()
-			for s in super_classes:
-				# workaround for multiple inheritance
-				self.out.write("var proto = new " + s + "();")
-				self.out.write("for (prop in proto) {")
-				self.out.indent()
-				self.out.write(class_name + ".prototype[prop] = proto[prop];")
-				self.out.dedent()
-				self.out.write("}")
-			self.out.dedent()
-			self.out.write("})();")
-		self.writeAll(c.getMembers())
-
-	def visit_Constructor(self, constructor):
-		class_name = constructor.getClass().getIdentifier()
-		parameters = constructor.getFormalParameters()
-		body = constructor.getBody()
-
-		self.out.write("var " + class_name + " = function")
-		parameters.accept(self)
-		body.accept(self)
-		self.out.extendWrite(";")
-
-	def visit_EqualsOperator(self, e):
-		self.out.extendWrite(" === ")
-
-	def visit_ForLoopBody(self, body):
-		for_loop = body.getForLoop()
-		collection_expr = for_loop.getCollectionExpression()
-		iterator_identifier = for_loop.getIteratorIdentifier()
-
-		self.out.extendWrite(" {")
-		self.out.indent()
-		self.out.write("if (!")
-		collection_expr.accept(self)
-		self.out.extendWrite(".hasOwnProperty(" + iterator_identifier + ")) continue;")
-		self.writeAll(body.getEntries())
-		self.out.dedent()
-		self.out.write("}")
-
-	def visit_ForLoopCurrentElement(self, el):
-		collection = el.getCollectionExpression()
-		iterator = el.getIteratorIdentifier()
-
-		collection.accept(self)
-		self.out.extendWrite("["+iterator+"]")
-
-	def visit_ForLoopIterateArray(self, loop):
-		collection = loop.getCollectionExpression()
-		iterator = loop.getIteratorIdentifier()
-		body = loop.getBody()
-
-		self.out.write("for (var " + iterator + " in ")
-		collection.accept(self)
-		self.out.extendWrite(")")
-		body.accept(self)
-
-	def visit_ForLoopIterateMapValues(self, loop):
-		collection = loop.getCollectionExpression()
-		iterator = loop.getIteratorIdentifier()
-		body = loop.getBody()
-
-		self.out.write("for (var " + iterator + " in ")
-		collection.accept(self)
-		self.out.extendWrite(")")
-		body.accept(self)
-
-	def visit_FormalParameter(self, parameter):
-		self.out.extendWrite(parameter.getIdentifier())
-
-	def visit_IncludeStatement(self, i):
-		pass # javascript doesn't have an include mechanism
-
-	def visit_LocalVariableDeclaration(self, decl):
-		identifier = decl.getIdentifier()
-		init_value = decl.getInitValue()
-
-		self.out.extendWrite("var " + identifier)
-		if init_value:
-			self.out.extendWrite(" = ")
-			init_value.accept(self)
-
-	def visit_LogStatement(self, l):
-		self.out.write("console.log(\"" + l.getMessage() + "\");")
-
-	def visit_MapExpression(self, m):
-		elements = m.getElements()
-		if len(elements) == 0:
-			self.out.extendWrite("new Object()")
-		else:
-			self.out.extendWrite("{")
-			keys = list(elements.keys())
-			for i in range(len(keys)):
-				if i != 0:
-					self.out.extendWrite(", ")			
-				self.out.extendWrite(keys[i] + " : ")
-				self.out.extendWrite(" : ")
-				elements[keys[i]].accept(self)
-			self.out.extendWrite("}")
-
-	def visit_MapIndexedExpression(self, i):
-		m = i.getMapExpression()
-		key = i.getKeyExpression()
-
-		m.accept(self)
-		self.out.extendWrite("[")
-		key.accept(self)
-		self.out.extendWrite("]")
-
-	def visit_MapRemoveElement(self, stmt):
-		map_expr = stmt.getMapExpression()
-		key_expr = stmt.getKeyExpression()
-
-		self.out.write("delete ") # this is a statement, not an expression
-		map_expr.accept(self)
-		self.out.extendWrite("[")
-		key_expr.accept(self)
-		self.out.extendWrite("];")		
-
-	def visit_Method(self, method):
-		class_name = method.getClass().getIdentifier()
-		method_name = method.getIdentifier()
-		description = method.getDescription()
-		body = method.getBody()
-		parameters = method.getFormalParameters()
-
-		self.out.write()
-		if description:
-			self.writeComment(description)
-		self.writeDescription(method)
-		self.out.write(class_name + ".prototype." + method_name + " = function")
-		parameters.accept(self)
-		body.accept(self)
-		self.out.extendWrite(";")
-
-	def visit_MethodBody(self, body):
-		method = body.getMethod()
-		formal_parameters = method.getFormalParameters()
-		formal_parameter_list = formal_parameters.getParameterList()
-
-		self.out.extendWrite(" {")
-		self.out.indent()
-		# check for undefined parameters and replace them with default values
-		for p in formal_parameter_list:
-			p_id = p.getIdentifier()
-			p_default = p.getDefaultValue()
-			if p_default:
-				self.out.write("if (" + p_id + " === undefined) " + p_id + " = ")
-				p_default.accept(self)
-				self.out.extendWrite(";")
-		self.writeAll(body.getEntries())
-		self.out.dedent()
-		self.out.write("}")
-
-	def visit_NoneExpression(self, n):
-		self.out.extendWrite("null")
-
-	def visit_Package(self, package):
-		name = package.getIdentifier()
-		description = package.getDescription()
-
-		self.writeComment("package \"" + name + "\"")
-		if description:
-			self.writeComment(description)
-		self.out.write("var " + name + " = {};")
-		self.out.write("(function() {")
-		for d in package.getDeclarations():
-			d_id = d.getIdentifier()
-			d.accept(self)
-			self.out.write()
-			self.out.write("// add symbol '" + d_id + "' to package '" + name + "'")
-			self.out.write(name + "." + d_id + " = " + d_id + ";")
-		self.out.write("})();")
-
-	def visit_RuntimeModuleIdentifier(self, r):
-		self.out.extendWrite("javascript_runtime")
-
-	def visit_StaticAttribute(self, attr):
-		name = attr.getIdentifier()
-		init_value = attr.getInitValue()
-		class_name = attr.getClass().getIdentifier()
-
-		if init_value:
-			self.out.write(class_name + ".prototype." + name + " = ")
-			init_value.accept(self)
-			self.out.extendWrite(";")
-		else:
-			self.out.write(class_name + ".prototype." + name + " = null;")
-
-	def visit_SuperClassConstructorCall(self, call):
-		super_class = call.getSuperClassIdentifier()
-		params = call.getActualParameters()
-		param_list = [Literal("this")] + params.getParameterList()
-		params = ActualParameters(param_list)
-
-		self.out.extendWrite(super_class)
-		self.out.extendWrite(".call")
-		params.accept(self)
-
-	def visit_SuperClassDestructorCall(self, call):
-		pass # Javascript doesn't have destructors
-
-	def visit_SuperClassMethodCall(self, call):
-		super_class = call.getSuperClassIdentifier()
-		method_name = call.getMethodIdentifier()
-		params = call.getActualParameters()
-		param_list = [Literal("this")] + params.getParameterList()
-		params = ActualParameters(param_list)
-
-		self.out.extendWrite(super_class)
-		self.out.extendWrite(".prototype." + method_name + ".call")
-		params.accept(self)
-
-	def visit_ThrowExceptionStatement(self, stmt):
-		self.out.write("throw new Error(")
-		stmt.getExpression().accept(self)
-		self.out.extendWrite(");")
-
-

+ 0 - 170
kernel/mvk_server/python_sccd_compiler/lexer.py

@@ -1,170 +0,0 @@
-from kernel.mvk_server.python_sccd_compiler.utils import Enum
-
-TokenType = Enum("SLASH",
-				 "LBRACKET",
-				 "RBRACKET",
-				 "COMMA",
-				 "DOT",
-				 "NUMBER",
-				 "WORD",
-				 "QUOTED",
-				 "WHITESPACE",
-				 "BINARYOPERATOR",
-				 "UNARYOPERATOR",
-				 "UNKNOWN"
-				)
-
-class Token(object):
-	""" A simple Token structure. Token type, value and position.
-	"""
-	def __init__(self, token_type, val, pos):
-		self.type = token_type
-		self.val = val
-		self.pos = pos
-
-	def __str__(self):
-		return '%s(%s) at %s' % (TokenType.name_of(self.type), self.val, self.pos)
-
-
-class LexerError(Exception):
-	def __init__(self, pos):
-		self.pos = pos
-		
-class Lexer(object):
-	single_rules = {
-			'/': TokenType.SLASH,
-			'(': TokenType.LBRACKET,
-			')': TokenType.RBRACKET,
-			',': TokenType.COMMA,
-			'.': TokenType.DOT,
-			'+': TokenType.BINARYOPERATOR,
-			'-': TokenType.BINARYOPERATOR,
-			'<': TokenType.BINARYOPERATOR,
-			'>': TokenType.BINARYOPERATOR,
-			'==': TokenType.BINARYOPERATOR,
-			'<=': TokenType.BINARYOPERATOR,
-			'>=': TokenType.BINARYOPERATOR,
-			'=': TokenType.BINARYOPERATOR,
-			'+=': TokenType.BINARYOPERATOR,
-			'-=': TokenType.BINARYOPERATOR,
-			'&&': TokenType.BINARYOPERATOR,
-			'||': TokenType.BINARYOPERATOR,
-			'!': TokenType.UNARYOPERATOR}
-	
-	def __init__(self, skip_white_space = True, accept_unknown_tokens = False):
-		self.skip_white_space = skip_white_space
-		self.accept_unknown_tokens = accept_unknown_tokens
-
-	def input(self, buf):
-		""" Initialize the lexer with a buffer as input.
-		"""
-		self.buf = buf
-		self.pos = 0
-		self.buflen = len(buf)
-
-	def nextToken(self):
-		""" Return the next token (a Token object) found in the
-			input buffer. None is returned if the end of the
-			buffer was reached.
-			In case of a lexing error (the current chunk of the
-			buffer matches no rule), a LexerError is raised.
-		"""
-		if self.skip_white_space :
-			self.skipWhiteSpace() 
-		if self.pos >= self.buflen:
-			return None
-
-		#c part of next token
-		c = self.buf[self.pos]
-		
-		#check if it is an operator
-		result_type = self.single_rules.get(c,None)
-		if result_type is not None :
-			if self.pos < self.buflen-1:
-				c2 = c+self.buf[self.pos+1]
-				result_type2 = self.single_rules.get(c2, None)
-				if result_type2 is not None:
-					c = c2
-					result_type = result_type2
-					self.pos += 1
-			token = Token(result_type, c, self.pos)
-			self.pos += 1
-			return token
-		else : #not an operator
-			if (self.isAlpha(c)) :
-				return self.processIdentifier()
-			elif (self.isDigit(c)) :
-				return self.processNumber()
-			elif ( c == "'" or c == '"') :
-				return self.processQuote()
-			elif (self.isWhiteSpace(c)) :
-				return self.processWhiteSpace()
-
-		# if we're here, no rule matched
-		if self.accept_unknown_tokens :
-			token = Token(TokenType.UNKNOWN, c, self.pos)
-			self.pos += 1
-			return token
-		raise LexerError("Invalid character at position " + str(self.pos) + ".")
-
-	def tokens(self):
-		""" Returns an iterator to the tokens found in the buffer.
-		"""
-		while True:
-			tok = self.nextToken()
-			if tok is None: break
-			yield tok
-			
-	def skipWhiteSpace(self):
-		while (self.pos < self.buflen) : 
-			if self.isWhiteSpace(self.buf[self.pos]) :
-				self.pos += 1
-			else :
-				break	  
-			
-	def isAlpha(self, c):
-		return c.isalpha() or c == '_';
-	
-	def isAlphaNum(self, c):
-		return c.isalnum() or c == '_';
-	
-	def isDigit(self, c):
-		return c.isdigit()
-	
-	def isWhiteSpace(self, c):
-		return c == ' ' or c == '\t' or c == '\r' or c == '\n'
-	
-	def processNumber(self):
-		nextpos = self.pos + 1
-		while (nextpos < self.buflen) and (self.isDigit(self.buf[nextpos])) :
-			nextpos += 1;
-		token = Token(TokenType.NUMBER, self.buf[self.pos:nextpos], self.pos)
-		self.pos = nextpos
-		return token
-	
-	def processIdentifier(self):
-		nextpos = self.pos + 1
-		while (nextpos < self.buflen) and (self.isAlphaNum(self.buf[nextpos])) :
-			nextpos += 1;
-		token = Token(TokenType.WORD, self.buf[self.pos:nextpos], self.pos)
-		self.pos = nextpos
-		return token
-	
-	def processQuote(self):
-		# self.pos points at the opening quote. Find the ending quote.
-		end_index = self.buf.find(self.buf[self.pos], self.pos + 1)
-	
-		if (end_index == -1) :
-			raise LexerError("Missing matching quote for the quote at position " + str(self.pos) + ".")
-		token = Token(TokenType.QUOTED, self.buf[self.pos:end_index+1], self.pos)
-
-		self.pos = end_index + 1;
-		return token;
-	
-	def processWhiteSpace(self):
-		nextpos = self.pos + 1
-		while (nextpos < self.buflen) and (self.isWhiteSpace(self.buf[nextpos])) :
-			nextpos += 1;
-		token = Token(TokenType.WHITESPACE, self.buf[self.pos:nextpos], self.pos)
-		self.pos = nextpos
-		return token

+ 0 - 701
kernel/mvk_server/python_sccd_compiler/old_generators/csharp_generator.py

@@ -1,701 +0,0 @@
-"""Generates C#"""
-
-import time
-from constructs import FormalParameter
-from code_generation import CodeGenerator, Platforms
-
-class CSharpGenerator(CodeGenerator):
-    
-    def __init__(self):
-        self.supported_platforms = [Platforms.Threads, Platforms.GameLoop]
-                
-    def visit_ClassDiagram(self, class_diagram):
-        self.fOut.write("/*")
-        self.fOut.indent()
-        self.fOut.write("Statecharts + Class Diagram compiler by Glenn De Jonghe")
-        self.fOut.write()
-        self.fOut.write("Date:   " + time.asctime())
-        if class_diagram.name or class_diagram.author or class_diagram.description:
-            self.fOut.write()
-        if class_diagram.author:
-            self.fOut.write("Model author: " + class_diagram.author)
-        if class_diagram.name:
-            self.fOut.write("Model name:   " + class_diagram.name)
-        if class_diagram.description.strip():
-            self.fOut.write("Model description:")
-            self.fOut.write()
-            self.fOut.indent()
-            self.fOut.write(class_diagram.description.strip())
-            self.fOut.dedent()
-        self.fOut.dedent()
-        self.fOut.write('*/')
-        self.fOut.write()
-        
-        #Namespace using declarations by the user
-        self.fOut.write('using System;')
-        self.fOut.write('using System.Collections.Generic;')
-        self.fOut.write('using sccdlib;')
-
-        #User imports
-        if class_diagram.top.strip():
-            self.writeCodeCorrectIndent(class_diagram.top)
-        self.fOut.write()
-        
-        #visit children
-        for c in class_diagram.classes :
-            c.accept(self)
-         
-        #writing out ObjectManager
-        self.fOut.write('public class ObjectManager : ObjectManagerBase')
-        self.fOut.write('{')
-        self.fOut.indent()
-        self.fOut.write('public ObjectManager(ControllerBase controller): base(controller)')
-        self.fOut.write("{")
-        self.fOut.write("}")
-        self.fOut.write()
-        
-        self.fOut.write('protected override InstanceWrapper instantiate(string class_name, object[] construct_params)')
-        self.fOut.write('{')
-        self.fOut.indent()
-        self.fOut.write("RuntimeClassBase instance = null;")
-        self.fOut.write("List<Association> associations = new List<Association>();")
-        for index, c in enumerate(class_diagram.classes) :
-            if index == 0 :
-                self.fOut.write()
-            else :
-                self.fOut.write('}else ')
-            self.fOut.extendWrite('if (class_name == "' + c.name + '" ){')
-            self.fOut.indent()
-            self.fOut.write('object[] new_parameters = new object[construct_params.Length + 1];')
-            self.fOut.write('new_parameters[0] = this.controller;')
-            self.fOut.write('Array.Copy(construct_params, 0, new_parameters, 1, construct_params.Length);')
-            self.fOut.write('instance = (RuntimeClassBase) Activator.CreateInstance(typeof(' + c.name + '), new_parameters);')
-            for a in c.associations :
-                a.accept(self)
-            self.fOut.dedent()
-            if index == len(class_diagram.classes)-1 :
-                self.fOut.write('}')
-            
-        self.fOut.write('if (instance != null) {')
-        self.fOut.indent()
-        self.fOut.write('return new InstanceWrapper(instance, associations);')
-        self.fOut.dedent()
-        self.fOut.write('}')
-        self.fOut.write('return null;')
-        self.fOut.dedent()
-        self.fOut.write('}')
-        self.fOut.dedent()
-        self.fOut.write('}')
-        
-        # write out controller
-        self.fOut.write()
-        if self.platform == Platforms.Threads :
-            controller_sub_class = "ThreadsControllerBase"
-        elif self.platform == Platforms.GameLoop :
-            controller_sub_class = "GameLoopControllerBase"
-        self.fOut.write("public class Controller : " + controller_sub_class)
-        self.fOut.write("{")
-        self.fOut.indent()
-    
-        # write out constructor(s)
-        if class_diagram.default_class.constructors :
-            for constructor in class_diagram.default_class.constructors :
-                self.writeControllerConstructor(class_diagram, constructor.parameters)
-        else :
-            self.writeControllerConstructor(class_diagram)
-        
-        self.fOut.write("public static void Main()")
-        self.fOut.write("{")
-        self.fOut.indent()
-        self.fOut.write("Controller controller = new Controller();")
-        self.fOut.write("controller.start();")
-        self.fOut.dedent()
-        self.fOut.write("}")
-        
-        self.fOut.dedent()
-        self.fOut.write("}")
-        
-    #helper method
-    def writeControllerConstructor(self, class_diagram, parameters = []):
-        self.fOut.write('public Controller(')
-        self.writeFormalParameters(parameters + [FormalParameter("keep_running", "bool", "true")])
-        self.fOut.extendWrite(") : base(keep_running)")
-        self.fOut.write('{')
-        self.fOut.indent()
-        
-        for p in class_diagram.inports:
-            self.fOut.write('this.addInputPort("' + p + '");')
-        for p in class_diagram.outports:
-            self.fOut.write('this.addOutputPort("' + p + '");')
-        self.fOut.write('this.object_manager = new ObjectManager(this);')
-        actual_parameters = [p.getIdent() for p in parameters]
-        self.fOut.write('this.object_manager.createInstance("'+ class_diagram.default_class.name +'", new object[]{' +  ', '.join(actual_parameters)+ '});')
-        self.fOut.dedent()
-        self.fOut.write('}')
-
-    def visit_Class(self, class_node):
-        """
-        Generate code for Class construct
-        """
-        self.fOut.write()
-        self.fOut.write("public class " + class_node.name )
-        # Take care of inheritance
-        if len(class_node.super_classes) > 1 :
-            raise Exception("C# doesn't allow multiple inheritance.");
-        elif len(class_node.super_classes) == 1 :
-            self.fOut.extendWrite(" : " + class_node.super_classes[0])
-        else :
-            self.fOut.extendWrite(" : " + "RuntimeClassBase")
-        self.fOut.write("{")
-        self.fOut.indent()
-        self.fOut.write()
-        
-        if class_node.statechart is not None:
-            # assign each node a unique ID
-            self.fOut.write("/// <summary>")
-            self.fOut.write("/// Enum uniquely representing all statechart nodes.")
-            self.fOut.write("/// </summary>")
-            self.fOut.write("public enum Node {")
-            self.fOut.indent()
-            for node in class_node.statechart.composites + class_node.statechart.basics:
-                self.fOut.write(node.full_name + ",");
-            self.fOut.dedent();
-            self.fOut.write("};")
-            self.fOut.write()
-            self.fOut.write("Dictionary<Node,List<Node>> current_state = new Dictionary<Node,List<Node>>();");
-            if len(class_node.statechart.histories) > 0 :
-                self.fOut.write("Dictionary<Node,List<Node>> history_state = new Dictionary<Node,List<Node>>();");
-            self.fOut.write();
-            
-        #User defined attributes
-        if class_node.attributes:
-            self.fOut.write("//User defined attributes")
-            for attribute in class_node.attributes:
-                self.fOut.write(attribute.type + " " + attribute.name)
-                if attribute.init_value is not None :
-                    self.fOut.write(" = " + attribute.init_value);
-                self.fOut.extendWrite(";")     
-            self.fOut.write()
-
-        if class_node.statechart is not None:  
-            self.fOut.write("/// <summary>")
-            self.fOut.write("/// Constructor part that is common for all constructors.")
-            self.fOut.write("/// </summary>")
-            self.fOut.write("private void commonConstructor(ControllerBase controller = null)")
-            self.fOut.write("{")
-            self.fOut.indent() 
-            self.fOut.write("this.controller = controller;")
-            self.fOut.write("this.object_manager = controller.getObjectManager();")
-            if class_node.statechart.nr_of_after_transitions != 0:
-                self.fOut.write("this.timers = new Dictionary<int,double>();")
-
-            self.fOut.write()
-            self.fOut.write("//Initialize statechart :")
-            self.fOut.write()
-
-            if class_node.statechart.histories:
-                for node in class_node.statechart.combined_history_parents:
-                    self.fOut.write("this.history_state[Node." + node.full_name + "] = new List<Node>();")
-                self.fOut.write()
-
-            for node in class_node.statechart.composites :
-                self.fOut.write("this.current_state[Node." + node.full_name + "] = new List<Node>();")
-                
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write()
-        
-        self.fOut.write("public override void start()")
-        self.fOut.write("{")
-        
-        self.fOut.indent()
-        self.fOut.write("base.start();")
-        for default_node in class_node.statechart.root.defaults:
-            if default_node.is_composite:
-                self.fOut.write("this.enterDefault_" + default_node.full_name + "();")
-            elif default_node.is_basic:
-                self.fOut.write("this.enter_" + default_node.full_name + "();")
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write()
-        
-        #visit children
-        for i in class_node.constructors :
-            i.accept(self)
-        for i in class_node.destructors :
-            i.accept(self)
-        for i in class_node.methods :
-            i.accept(self)
-        if class_node.statechart is not None:
-            class_node.statechart.accept(self)
-          
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write()
-
-    def writeFormalParameters(self, parameters = []):
-        """Helper method that writes a correct comma separated list of formal parameters"""    
-        first = True       
-        for param in parameters :
-            if first :
-                first = False
-            else :
-                self.fOut.extendWrite(', ')
-            param.accept(self)
-        
-    def visit_FormalParameter(self, formal_parameter):
-        self.fOut.extendWrite(formal_parameter.getType() + " " + formal_parameter.getIdent())
-        if formal_parameter.hasDefault() :
-            self.fOut.extendWrite(" = " + formal_parameter.getDefault())
-                    
-    def visit_Constructor(self, constructor):
-
-        self.fOut.write(constructor.access + " " + constructor.parent_class.name + "(")
-        self.writeFormalParameters([FormalParameter("controller", "ControllerBase", None)] + constructor.getParams())
-        self.fOut.extendWrite(")")
-        self.fOut.write("{")
-        self.fOut.indent()
-        self.fOut.write("this.commonConstructor(controller);")
-        if constructor.body :
-            self.fOut.write()
-            self.fOut.write("//constructor body (user-defined)")
-            self.writeCodeCorrectIndent(constructor.body)
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write()
-        
-    def visit_Destructor(self, destructor):
-        self.fOut.write("~" + destructor.parent_class.name + "()")
-        self.fOut.write("{")
-        if destructor.body :
-            self.fOut.indent()
-            self.writeCodeCorrectIndent(destructor.body)
-            self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write()
-        
-    def visit_Method(self, method):
-        self.fOut.write(method.access + " " + method.return_type + " " + method.name + "(")
-        self.writeFormalParameters(method.getParams())
-        self.fOut.extendWrite(")")
-        self.fOut.write("{")
-        self.fOut.indent()
-        if method.body :
-            self.fOut.indent()
-            self.writeCodeCorrectIndent(method.body)
-            self.fOut.dedent()
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write()
-        
-    def visit_Association(self, association):
-        self.fOut.write('associations.Add(new Association("' + association.name + '", "' + association.to_class + '", ' + str(association.min) + ', ' + str(association.max) + '));')
-        
-    #helper method
-    def writeTransitionsRecursively(self, current_node):
-        self.fOut.write("private bool transition_" + current_node.full_name + "(Event e)")
-        self.fOut.write("{")
-        self.fOut.indent()
-        
-        valid_children = []
-        for child in current_node.children :
-            if child.is_composite or child.is_basic :
-                valid_children.append(child)  
-         
-        self.fOut.write("bool catched = false;")
-        do_dedent = False
-        if current_node.solves_conflict_outer :
-            self.writeFromTransitions(current_node)
-            if current_node.is_parallel_state or current_node.is_composite :
-                self.fOut.write("if (!catched){")
-                self.fOut.indent()
-                do_dedent = True
-            
-        if current_node.is_parallel_state:
-            for child in valid_children :     
-                self.fOut.write("catched = this.transition_" + child.full_name + "(e) || catched;")
-        elif current_node.is_composite:
-            self.fOut.write()
-            for i, child in enumerate(valid_children) :
-                if i > 0 :
-                    self.fOut.extendWrite(" else ")
-                self.fOut.extendWrite("if (this.current_state[Node." + current_node.full_name + "][0] == Node." + child.full_name + "){")
-                self.fOut.indent()
-                self.fOut.write("catched = this.transition_" + child.full_name + "(e);")
-                self.fOut.dedent()
-                self.fOut.write("}")
-                
-        if current_node.solves_conflict_outer :
-            if do_dedent :
-                self.fOut.dedent()
-                self.fOut.write("}")
-        elif len(current_node.transitions) > 0 :
-                self.fOut.write("if (!catched) {")
-                self.fOut.indent()
-                self.writeFromTransitions(current_node)
-                self.fOut.dedent()
-                self.fOut.write("}")
-            
-        self.fOut.write("return catched;")
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write();
-        
-        for child in valid_children :
-            self.writeTransitionsRecursively(child)
-                
-    #helper method
-    def writeFromTransitions(self, current_node): 
-        # get all transition out of this state
-        out_transitions = current_node.transitions
-        if len(out_transitions) == 0 :
-            return
-        
-        self.fOut.write('List<int> enableds = new List<int>();')
-        for index, transition in enumerate(out_transitions):
-            self.writeTransitionCondition(transition, index)
-            
-        self.fOut.write("if (enableds.Count > 1){")
-        self.fOut.indent()
-        self.fOut.write('Console.WriteLine("Runtime warning : indeterminism detected in a transition from node ' +  current_node.full_name+ '. Only the first in document order enabled transition is executed.");')
-        self.fOut.dedent()
-        self.fOut.write('}')
-        self.fOut.write("if (enableds.Count > 0){")
-        self.fOut.indent()
-        self.fOut.write('int enabled = enableds[0];')
-        self.fOut.write()      
-              
-        for index, transition in enumerate(out_transitions):
-            self.writeTransitionAction(transition, index)
-        
-        self.fOut.write('catched = true;')   
-        self.fOut.dedent()
-        self.fOut.write('}')         
-        self.fOut.write()
-        
-    def visit_FormalEventParameter(self, formal_event_parameter):
-        self.fOut.extendWrite(formal_event_parameter.getType() + " " + formal_event_parameter.name)
-        
-    def writeFormalEventParameters(self, transition):
-        parameters = transition.getTrigger().getParameters()
-        if(len(parameters) > 0) :
-            self.fOut.write('object[] parameters = e.getParameters();')
-            for index, parameter in enumerate(parameters):
-                self.fOut.write()
-                parameter.accept(self)
-                self.fOut.extendWrite(' = (' + parameter.getType() + ')parameters[' + str(index) + '];')
-        
-    def writeTransitionAction(self, transition, index):
-        if index > 1 :
-            self.fOut.extendWrite(" else ")
-        else :
-            self.fOut.write()
-        self.fOut.extendWrite("if (enabled == " + str(index) + "){")
-        self.fOut.indent()
-
-        # handle parameters to actually use them             
-        self.writeFormalEventParameters(transition)
-        
-        exits = transition.getExitNodes()
-        
-        # write out exit actions
-        if not exits[-1].is_basic:
-            self.fOut.write("this.exit_" + exits[-1].full_name + "();")
-        else:
-            for node in exits:
-                if node.is_basic:
-                    self.fOut.write("this.exit_" + node.full_name + "();")
-                    
-        # write out trigger actions
-        transition.getAction().accept(self)
-        
-        for (entering_node, is_ending_node) in transition.getEnterNodes() : 
-            if is_ending_node :
-                if entering_node.is_composite:
-                    self.fOut.write("this.enterDefault_" + entering_node.full_name + "();")
-                elif entering_node.is_history:
-                    if (entering_node.is_history_deep) :
-                        self.fOut.write("this.enterHistoryDeep_" + entering_node.parent.full_name + "();")
-                    else :
-                        self.fOut.write("this.enterHistoryShallow_" + entering_node.parent.full_name + "();")
-                else:
-                    self.fOut.write("this.enter_" + entering_node.full_name + "();")
-            else :
-                if entering_node.is_composite:
-                    self.fOut.write("this.enter_" + entering_node.full_name + "();")
-
-        self.fOut.dedent()
-        self.fOut.write('}')
-                        
-    def writeTransitionCondition(self, transition, index):
-        trigger = transition.getTrigger()
-        if not trigger.isUC():  
-            self.fOut.write('if (e.getName() == "' + trigger.getEvent() + '" && e.getPort() == "' + trigger.getPort() + '"){')
-            self.fOut.indent()   
-        # evaluate guard
-        if transition.hasGuard() :   
-            # handle parameters for guard evaluation       
-            self.writeFormalEventParameters(transition)  
-
-            self.fOut.write('if (')
-            transition.getGuard().accept(self)
-            self.fOut.extendWrite('){')
-            self.fOut.indent()    
-            
-        self.fOut.write("enableds.Add(" + str(index) + ");")
-
-        if transition.hasGuard() :
-            self.fOut.dedent()
-            self.fOut.write('}')
-        if not trigger.isUC() :
-            self.fOut.dedent()
-            self.fOut.write('}')
-        self.fOut.write()
-    
-    def visit_EnterAction(self, enter_method):
-        parent_node = enter_method.parent_node
-        self.fOut.write("private void enter_" + parent_node.full_name + "()")
-        self.fOut.write("{")
-        self.fOut.indent()
-        
-        # take care of any AFTER events
-        for transition in parent_node.transitions :
-            trigger = transition.getTrigger()
-            if trigger.isAfter() :
-                self.fOut.write("this.timers[" + str(trigger.getAfterIndex()) + "] = ")
-                trigger.after.accept(self)
-                self.fOut.extendWrite(";")
-        if enter_method.action:
-            enter_method.action.accept(self)
-        self.fOut.write("this.current_state[Node." + parent_node.parent.full_name + "].Add(Node." + parent_node.full_name + ");")
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write()
-        
-    #helper method
-    def writeEnterDefault(self, entered_node):
-        self.fOut.write("private void enterDefault_" + entered_node.full_name + "()")
-        self.fOut.write("{")
-        self.fOut.indent()
-        self.fOut.write("this.enter_" + entered_node.full_name + "();")
-        if entered_node.is_composite:
-            l = entered_node.defaults
-            for i in l:
-                if i.is_composite:
-                    self.fOut.write("this.enterDefault_" + i.full_name + "();")
-                elif i.is_basic:
-                    self.fOut.write("this.enter_" + i.full_name + "();")
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write()
-         
-    def visit_ExitAction(self, exit_method):
-        exited_node = exit_method.parent_node
-        self.fOut.write("private void exit_" + exited_node.full_name + "()")
-        self.fOut.write("{")
-        self.fOut.indent()
-        #If the exited node is composite take care of potential history and the leaving of descendants
-        if exited_node.is_composite :
-            #handle history
-            if exited_node.save_state_on_exit:
-                self.fOut.write("this.history_state[Node." + exited_node.full_name + "].AddRange(this.current_state[Node." + exited_node.full_name + "]);")
-            
-            #Take care of leaving children
-            children = exited_node.children
-            if exited_node.is_parallel_state:
-                for child in children:
-                    if not child.is_history :
-                        self.fOut.write("this.exit_" + child.full_name + "();")
-            else:
-                for child in children:
-                    if not child.is_history :
-                        self.fOut.write("if (this.current_state[Node." + exited_node.full_name + "].Contains(Node." + child.full_name +  ")){")
-                        self.fOut.indent()
-                        self.fOut.write("this.exit_" + child.full_name + "();")
-                        self.fOut.dedent()  
-                        self.fOut.write("}")
-        
-        
-        # take care of any AFTER events
-        for transition in exited_node.transitions :
-            trigger = transition.getTrigger()
-            if trigger.isAfter() :
-                self.fOut.write("this.timers.Remove(" + str(trigger.getAfterIndex()) + ");")
-                
-        #Execute user-defined exit action if present
-        if exit_method.action:
-            exit_method.action.accept(self)
-            
-        #Adjust state
-        self.fOut.write("this.current_state[Node." + exited_node.parent.full_name + "].Remove(Node." + exited_node.full_name + ");")
-
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write()
-        
-            
-    #helper method
-    def writeEnterHistory(self, entered_node, is_deep):
-        self.fOut.write("private void enterHistory" + ("Deep" if is_deep else "Shallow") + "_" + entered_node.full_name + "()")
-        self.fOut.write("{")
-        self.fOut.indent()
-        self.fOut.write("if (this.history_state[Node." + entered_node.full_name + "].Count == 0){")
-        self.fOut.indent()
-        defaults = entered_node.defaults
-
-        for node in defaults:
-            if node.is_basic :
-                self.fOut.write("this.enter_" + node.full_name + "();")
-            elif node.is_composite :
-                self.fOut.write("this.enterDefault_" + node.full_name + "();")
-
-        self.fOut.dedent()
-        self.fOut.write("} else {")
-        self.fOut.indent()
-        children = entered_node.children
-        if entered_node.is_parallel_state:
-            for child in children:
-                if not child.is_history :
-                    self.fOut.write("this.enterHistory" + ("Deep" if is_deep else "Shallow") + "_" + child.full_name + "();")
-        else:
-            for child in children:
-                if not child.is_history :
-                    self.fOut.write("if (this.history_state[Node." + entered_node.full_name + "].Contains(Node." + child.full_name + ")){")
-                    self.fOut.indent()
-                    if child.is_composite:
-                        if is_deep :
-                            self.fOut.write("this.enter_" + child.full_name + "();")
-                            self.fOut.write("this.enterHistoryDeep_" + child.full_name + "();")
-                        else :
-                            self.fOut.write("this.enterDefault_" + child.full_name + "();")
-                    else:
-                        self.fOut.write("this.enter_" + child.full_name + "();")
-                    self.fOut.dedent()
-                    self.fOut.write("}")
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write()
-
-    def visit_StateChart(self, statechart):
-        self.fOut.write("//Statechart enter/exit action method(s) :")
-        self.fOut.write()
-        
-        #visit enter and exit actions of children
-        for i in statechart.composites + statechart.basics:
-            if i is not statechart.root :
-                i.enter_action.accept(self)
-                i.exit_action.accept(self)
-
-        # write out statecharts methods for enter/exit state
-        if len(statechart.composites) > 1 :
-            self.fOut.write("//Statechart enter/exit default method(s) :")
-            self.fOut.write()
-            for i in statechart.composites :
-                if i is not statechart.root :
-                    self.writeEnterDefault(i)
-
-        # write out statecharts methods for enter/exit history
-        if statechart.histories:
-            self.fOut.write("//Statechart enter/exit history method(s) :")
-            self.fOut.write()
-            for i in statechart.shallow_history_parents:
-                self.writeEnterHistory(i, False)
-            for i in statechart.deep_history_parents:
-                self.writeEnterHistory(i, True)   
-                
-        self.fOut.write("//Statechart transitions :")
-        self.fOut.write()
-        self.writeTransitionsRecursively(statechart.root)            
-                
-        # write out transition function
-        self.fOut.write("protected override void transition (Event e = null)")
-        self.fOut.write("{")
-        self.fOut.indent()
-        self.fOut.write("if (e == null) {");
-        self.fOut.indent()
-        self.fOut.write("e = new Event();")
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write("this.state_changed = this.transition_" + statechart.root.full_name + "(e);")
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write()
-
-        # write out inState function
-        self.fOut.write("public bool inState(List<Node> nodes)")
-        self.fOut.write("{")
-        self.fOut.indent()
-        self.fOut.write("foreach(List<Node> actives in current_state.Values){")
-        self.fOut.indent()
-        self.fOut.write("foreach(Node node in actives)")
-        self.fOut.indent()
-        self.fOut.write("nodes.Remove (node);")
-        self.fOut.dedent()
-        self.fOut.write("if (nodes.Count == 0){")
-        self.fOut.indent()
-        self.fOut.write("return true;")
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write("return false;")
-        self.fOut.dedent()
-        self.fOut.write("}")
-        self.fOut.write()
-        
-    def visit_ExpressionPartString(self, bare_string):
-        self.fOut.extendWrite(bare_string.string)
-        
-    def visit_SelfReference(self, self_reference):
-        self.fOut.extendWrite("this")
-        
-    def visit_StateReference(self, state_ref):
-        self.fOut.extendWrite("new List<Node>() {")
-        self.fOut.extendWrite(", ".join(["Node." + node.full_name for node in state_ref.getNodes()]))
-        self.fOut.extendWrite("}")
-        
-    def visit_InStateCall(self, in_state_call):
-        self.fOut.extendWrite("this.inState(")
-        in_state_call.target.accept(self)
-        self.fOut.extendWrite(")")
-        
-    def visit_RaiseEvent(self, raise_event):
-        if raise_event.isNarrow() or raise_event.isBroad():
-            self.fOut.write('Event send_event = new Event("' + raise_event.getEventName() + '", "", new object[] {')
-        elif raise_event.isLocal():
-            self.fOut.write('this.addEvent( new Event("' + raise_event.getEventName() +'", "", new object[] {')
-        elif raise_event.isOutput():
-            self.fOut.write('this.controller.outputEvent(new Event("' + raise_event.getEventName() + '", "' + raise_event.getPort() + '", new object[] {')
-        elif raise_event.isCD():
-            self.fOut.write('this.object_manager.addEvent(new Event("' + raise_event.getEventName() + '", "", new object[] { this, ')
-        first_param = True
-        for param in raise_event.getParameters() :
-            if first_param :
-                first_param = False
-            else :
-                self.fOut.extendWrite(',')
-            param.accept(self)
-        if raise_event.isNarrow():
-            self.fOut.extendWrite('});')
-            self.fOut.write('this.object_manager.addEvent(new Event("narrow_cast", "", new object[] {this, "' + raise_event.getTarget() + '" ,send_event}));')
-        elif raise_event.isBroad():
-            self.fOut.extendWrite('});')
-            self.fOut.write('this.object_manager.addEvent(new Event("broad_cast", "", new object[] {send_event}));')
-        else :
-            self.fOut.extendWrite('}));')
-            
-    def visit_Script(self, script):
-        self.writeCodeCorrectIndent(script.code)
-        
-    def visit_Log(self, log):
-        self.fOut.write('Console.WriteLine("' + log.message + '");')
-        
-    def visit_Assign(self, assign):
-        self.fOut.write()
-        assign.lvalue.accept(self)
-        self.fOut.extendWrite(" = ")
-        assign.expression.accept(self)
-        self.fOut.extendWrite(";")
-        

+ 0 - 0
kernel/mvk_server/python_sccd_compiler/old_generators/javascript_generator.py


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است