浏览代码

Merge branch 'master' into DEVS

Yentl Van Tendeloo 8 年之前
父节点
当前提交
b10f4f9870
共有 100 个文件被更改,包括 6233 次插入615 次删除
  1. 9 3
      .gitignore
  2. 3 3
      bootstrap/90_core_formalism.mvc
  3. 15 22
      bootstrap/bootstrap.py
  4. 4 4
      bootstrap/conformance_scd.alc
  5. 4 4
      bootstrap/constructors.alc
  6. 376 201
      bootstrap/core_algorithm.alc
  7. 25 0
      bootstrap/files.alc
  8. 1 0
      bootstrap/initial_code_task.alc
  9. 32 0
      bootstrap/io.alc
  10. 12 12
      bootstrap/mini_modify.alc
  11. 19 16
      bootstrap/model_management.alc
  12. 16 11
      bootstrap/modelling.alc
  13. 12 10
      bootstrap/object_operations.alc
  14. 6 16
      bootstrap/primitives.alc
  15. 22 4
      bootstrap/ramify.alc
  16. 13 2
      bootstrap/random.alc
  17. 83 12
      bootstrap/semi_primitives.alc
  18. 1 1
      bootstrap/services.alc
  19. 0 1
      bootstrap/tracability.mvc
  20. 11 11
      bootstrap/transform.alc
  21. 9 8
      bootstrap/typing.alc
  22. 45 1
      bootstrap/utils.alc
  23. 144 0
      doc/al_rules/all_rules.tex
  24. 11 0
      doc/al_rules/auto_gen.py
  25. 10 0
      doc/al_rules/render.sh
  26. 15 0
      doc/al_rules/rule_access__eval.dot
  27. 19 0
      doc/al_rules/rule_access__init.dot
  28. 16 0
      doc/al_rules/rule_assign__assign.dot
  29. 19 0
      doc/al_rules/rule_assign__init.dot
  30. 23 0
      doc/al_rules/rule_assign__value.dot
  31. 18 0
      doc/al_rules/rule_break.dot
  32. 30 0
      doc/al_rules/rule_call__call-no-params.dot
  33. 34 0
      doc/al_rules/rule_call__call-params.dot
  34. 37 0
      doc/al_rules/rule_call__params-first-multi.dot
  35. 38 0
      doc/al_rules/rule_call__params-first-single.dot
  36. 40 0
      doc/al_rules/rule_call__params-last.dot
  37. 39 0
      doc/al_rules/rule_call__params-next.dot
  38. 21 0
      doc/al_rules/rule_call__resolve-no-params.dot
  39. 19 0
      doc/al_rules/rule_call__resolve-params.dot
  40. 20 0
      doc/al_rules/rule_const.dot
  41. 16 0
      doc/al_rules/rule_continue.dot
  42. 25 0
      doc/al_rules/rule_declare__init.dot
  43. 25 0
      doc/al_rules/rule_global__init.dot
  44. 19 0
      doc/al_rules/rule_if__cond.dot
  45. 23 0
      doc/al_rules/rule_if__false-else.dot
  46. 16 0
      doc/al_rules/rule_if__false-nothing.dot
  47. 23 0
      doc/al_rules/rule_if__true.dot
  48. 25 0
      doc/al_rules/rule_input.dot
  49. 13 0
      doc/al_rules/rule_next__next.dot
  50. 19 0
      doc/al_rules/rule_next__no-next.dot
  51. 19 0
      doc/al_rules/rule_output__init.dot
  52. 23 0
      doc/al_rules/rule_output__output.dot
  53. 27 0
      doc/al_rules/rule_resolve__no-attr-global.dot
  54. 20 0
      doc/al_rules/rule_resolve__no-attr.dot
  55. 16 0
      doc/al_rules/rule_return__eval.dot
  56. 15 0
      doc/al_rules/rule_return__no-value.dot
  57. 19 0
      doc/al_rules/rule_return__value.dot
  58. 19 0
      doc/al_rules/rule_while__cond.dot
  59. 14 0
      doc/al_rules/rule_while__false.dot
  60. 23 0
      doc/al_rules/rule_while__true.dot
  61. 4 0
      doc/al_rules/template.tex
  62. 2 0
      hybrid_server/classes/mvkcontroller.xml
  63. 1 0
      hybrid_server/server.xml
  64. 2 2
      integration/code/pm_pn_reachability.mvc
  65. 1 1
      integration/code/pn_print.mvc
  66. 6 6
      integration/code/reachability.alc
  67. 4 4
      integration/code/reachability_subfunction.alc
  68. 4 4
      integration/code/reachabilitygraph_print.mvc
  69. 64 41
      integration/test_powerwindow.py
  70. 3 2
      interface/HUTN/hutn_compiler/semantics_visitor.py
  71. 1 0
      interface/HUTN/includes/files.alh
  72. 3 0
      interface/HUTN/includes/io.alh
  73. 1 1
      interface/HUTN/includes/mini_modify.alh
  74. 8 16
      interface/HUTN/includes/primitives.alh
  75. 1 0
      interface/HUTN/includes/random.alh
  76. 2 0
      interface/HUTN/includes/utils.alh
  77. 3 2
      interface/plot/main.py
  78. 67 0
      interface/simple_plot/main.py
  79. 4 12
      kernel/modelverse_jit/intrinsics.py
  80. 48 45
      kernel/modelverse_kernel/compiled.py
  81. 1261 0
      kernel/modelverse_kernel/generated.py
  82. 17 11
      kernel/modelverse_kernel/main.py
  83. 11 58
      kernel/modelverse_kernel/primitives.py
  84. 3 0
      kernel/modelverse_kernel/request_handler.py
  85. 2299 0
      kernel/rules/MvK_rules.mvc
  86. 30 0
      kernel/rules/MvK_rules_MM.mvc
  87. 6 0
      kernel/rules/files.mvc
  88. 114 0
      kernel/rules/to_graphviz.alc
  89. 424 0
      kernel/rules/to_python.alc
  90. 19 0
      kernel/rules/upload.py
  91. 15 0
      kernel/rules/write_files.alc
  92. 6 0
      kernel/test/instructions/test_instruction_call.py
  93. 56 67
      kernel/test/primitives/test_cast.py
  94. 1 0
      kernel/test/rules/test_rules_break.py
  95. 1 0
      kernel/test/rules/test_rules_continue.py
  96. 6 1
      kernel/test/rules/test_rules_input.py
  97. 0 0
      kernel/test_generated/__init__.py
  98. 0 0
      kernel/test_generated/instructions/__init__.py
  99. 65 0
      kernel/test_generated/instructions/test_instruction_access.py
  100. 0 0
      kernel/test_generated/instructions/test_instruction_assign.py

+ 9 - 3
.gitignore

@@ -1,9 +1,15 @@
+.*
 *.pyc
 *.pickle
+__pycache__
+hybrid_server/server.py
+perf_data.txt
+doc/al_rules/*.pdf
+doc/al_rules/*.eps
+*.aux
+*.log
 *.dot
 .cache
 *.swp
 *.swo
-__pycache__
-hybrid_server/server.py
-perf_data.txt
+.tmp_*

+ 3 - 3
bootstrap/90_core_formalism.mvc

@@ -23,11 +23,11 @@ SimpleClassDiagrams CoreFormalism {
                     return "Permissions has no string value"!
                 if (bool_not(string_len(self) == 3)):
                     return "Permissions string is not of correct length"!
-                if (bool_or(cast_s2i(string_get(self, 0)) < 0, cast_s2i(string_get(self, 0)) > 2)):
+                if (bool_or(cast_integer(string_get(self, 0)) < 0, cast_integer(string_get(self, 0)) > 2)):
                     return "Owner permission is not in range [0, 2]"!
-                if (bool_or(cast_s2i(string_get(self, 1)) < 0, cast_s2i(string_get(self, 1)) > 2)):
+                if (bool_or(cast_integer(string_get(self, 1)) < 0, cast_integer(string_get(self, 1)) > 2)):
                     return "Group permission is not in range [0, 2]"!
-                if (bool_or(cast_s2i(string_get(self, 2)) < 0, cast_s2i(string_get(self, 2)) > 2)):
+                if (bool_or(cast_integer(string_get(self, 2)) < 0, cast_integer(string_get(self, 2)) > 2)):
                     return "Other permission is not in range [0, 2]"!
                 return "OK"!
             $

+ 15 - 22
bootstrap/bootstrap.py

@@ -19,6 +19,7 @@ def bootstrap():
 
     task_frame = [  "evalstack",
                     "returnvalue",
+                    "symbols",
                     ]
 
     primitives = {  "integer_addition": ["Integer", "Integer", "Integer"],
@@ -39,22 +40,12 @@ def bootstrap():
                     "string_len": ["Integer", "String"],
                     "string_split": ["Element", "String", "String"],
                     "value_eq":  ["Boolean", "Element", "Element"],
-                    "cast_i2f": ["Float", "Integer"],
-                    "cast_i2s": ["String", "Integer"],
-                    "cast_i2b": ["Boolean", "Integer"],
-                    "cast_f2i": ["Integer", "Float"],
-                    "cast_f2b": ["Boolean", "Float"],
-                    "cast_f2s": ["String", "Float"],
-                    "cast_s2i": ["Integer", "String"],
-                    "cast_s2f": ["Float", "String"],
-                    "cast_s2b": ["Boolean", "String"],
-                    "cast_b2i": ["Integer", "Boolean"],
-                    "cast_b2f": ["Float", "Boolean"],
-                    "cast_b2s": ["String", "Boolean"],
-                    "cast_e2s": ["String", "Element"],
-                    "cast_a2s": ["String", "Action"],
-                    "cast_v2s": ["String", "Element"],
-                    "cast_id2s": ["String", "Element"],
+                    "cast_float": ["Float", "Element"],
+                    "cast_string": ["String", "Element"],
+                    "cast_boolean": ["Boolean", "Element"],
+                    "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"],
@@ -144,12 +135,14 @@ def bootstrap():
                             f.write("Node _func_params_%s()\n" % (param_encoding))
 
                             f.write('Node _name_%s("%s")\n' % (param_encoding, parameter_names[number]))
-                            f.write("Edge _param_link_%s(_func_params_%s, _func_params_%s)\n" % (param_encoding, function, param_encoding))
-                            f.write("Edge _param_link_str_%s(_param_link_%s, _name_%s)\n" % (param_encoding, param_encoding, param_encoding))
-
-                            f.write('Node _name_str_%s("name")\n' % param_encoding)
-                            f.write("Edge _param_name_%s(_func_params_%s, _name_%s)\n" % (param_encoding, param_encoding, param_encoding))
-                            f.write("Edge _param_name_str_%s(_param_name_%s, _name_str_%s)\n" % (param_encoding, param_encoding, param_encoding))
+                            #f.write("Edge _param_link_%s(_func_params_%s, _func_params_%s)\n" % (param_encoding, function, param_encoding))
+                            #f.write("Edge _param_link_str_%s(_param_link_%s, _name_%s)\n" % (param_encoding, param_encoding, param_encoding))
+                            f.write('Dict (_func_params_%s, "%s", _func_params_%s)\n' % (function, parameter_names[number], param_encoding))
+
+                            #f.write('Node _name_str_%s("name")\n' % param_encoding)
+                            #f.write("Edge _param_name_%s(_func_params_%s, _name_%s)\n" % (param_encoding, param_encoding, param_encoding))
+                            #f.write("Edge _param_name_str_%s(_param_name_%s, _name_str_%s)\n" % (param_encoding, param_encoding, param_encoding))
+                            f.write('Dict (_func_params_%s, "name", _name_%s)\n' % (param_encoding, param_encoding))
 
                 declare_primitive_class('primitives', primitives)
                 declare_primitive_class('jit', jit_primitives)

+ 4 - 4
bootstrap/conformance_scd.alc

@@ -159,10 +159,10 @@ String function conformance_scd(model : Element):
 				return "Type of element not in specified metamodel: " + model_info(model, model_name)!
 
 			if (is_edge(element)):
-				src_model = reverse_m[cast_id2s(read_edge_src(element))]
-				dst_model = reverse_m[cast_id2s(read_edge_dst(element))]
-				src_metamodel = reverse_mm[cast_id2s(read_edge_src(metamodel["model"][typing[model_name]]))]
-				dst_metamodel = reverse_mm[cast_id2s(read_edge_dst(metamodel["model"][typing[model_name]]))]
+				src_model = reverse_m[cast_id(read_edge_src(element))]
+				dst_model = reverse_m[cast_id(read_edge_dst(element))]
+				src_metamodel = reverse_mm[cast_id(read_edge_src(metamodel["model"][typing[model_name]]))]
+				dst_metamodel = reverse_mm[cast_id(read_edge_dst(metamodel["model"][typing[model_name]]))]
 
 				if (bool_not(is_nominal_instance(model, src_model, src_metamodel))):
 					log("got: " + src_model)

+ 4 - 4
bootstrap/constructors.alc

@@ -36,8 +36,8 @@ Element function construct_function_list(list : Element):
 		elif (command == "mutable_funcdef"):
 			result = construct_funcdef(True, list)
 		else:
-			log("ERROR (1): did not understand command " + cast_e2s(command))
-			output("ERROR: compiled code not understood: " + cast_e2s(command))
+			log("ERROR (1): did not understand command " + cast_value(command))
+			output("ERROR: compiled code not understood: " + cast_value(command))
 			return read_root()!
 
 		continue = list_pop_final(list)
@@ -218,8 +218,8 @@ Element function construct_unknown(list : Element):
 	elif (elem == "continue"):
 		return construct_continue(list)!
 	else:
-		log("ERROR (2): did not understand command " + cast_e2s(elem))
-		output("ERROR: compiled code not understood: " + cast_e2s(elem))
+		log("ERROR (2): did not understand command " + cast_value(elem))
+		output("ERROR: compiled code not understood: " + cast_value(elem))
 		return read_root()!
 
 Action function construct_if(list : Element):

+ 376 - 201
bootstrap/core_algorithm.alc

@@ -13,12 +13,15 @@ include "utils.alh"
 include "conformance_finding.alh"
 include "typing.alh"
 include "compiler.alh"
+include "random.alh"
+include "io.alh"
 
 String core_model_location = "models/core"
 
 Element core = ?
 String current_user_id
 Element caches
+Element pm_tasks = ?
 
 String function get_foldername(name : String):
 	Element result
@@ -30,10 +33,10 @@ String function get_foldername(name : String):
 
 	// 'result' now contains a list of entries which we have to join with the seperator
 	String str
-	str = list_pop(result, 0)
+	str = list_pop_final(result)
 
 	while (list_len(result) > 0):
-		str = string_join(str + "/", list_pop(result, 0))
+		str = cast_string(list_pop_final(result)) + "/" + str
 
 	return str!
 
@@ -75,8 +78,8 @@ String function get_instanceOf_link(model_id : String, metamodel_id : String):
 		log("WARNING: multiple instanceOf relations were detected for this model; picking one at random!")
 	elif (set_len(all_links) == 0):
 		log("No types found!")
-		log("Source model: " + cast_v2s(read_attribute(core, model_id, "name")))
-		log("Target meta-model: " + cast_v2s(read_attribute(core, metamodel_id, "name")))
+		log("Source model: " + cast_value(read_attribute(core, model_id, "name")))
+		log("Target meta-model: " + cast_value(read_attribute(core, metamodel_id, "name")))
 		return read_root()!
 	
 	choice = set_pop(all_links)
@@ -127,8 +130,8 @@ Element function get_full_model(model_id : String, metamodel_id : String):
 		return m!
 	else:
 		log("No type mapping could be deduced!")
-		log("Error for " + cast_v2s(read_attribute(core, model_id, "name")))
-		log(" and type " + cast_v2s(read_attribute(core, metamodel_id, "name")))
+		log("Error for " + cast_value(read_attribute(core, model_id, "name")))
+		log(" and type " + cast_value(read_attribute(core, metamodel_id, "name")))
 		return read_root()!
 
 Integer function get_relation_to_model(user_id : String, model_id : String):
@@ -256,9 +259,9 @@ String function get_entry_id(name : String):
 	String current
 	Integer i
 	Element elems
-	String current_part
 	String elem
 	Boolean found
+	String folder_name
 
 	if (name == ""):
 		return caches["root"]!
@@ -268,20 +271,18 @@ String function get_entry_id(name : String):
 			if (full_name(caches["models"][name]) == name):
 				return caches["models"][name]!
 
-	current = get_entry_id(get_foldername(name))
+	folder_name = get_foldername(name)
+	current = get_entry_id(folder_name)
 
 	if (current == ""):
 		return ""!
 
-	if (current_part != ""):
-		elems = allAssociationDestinations(core, current, "contains")
-		while (set_len(elems) > 0):
-			elem = set_pop(elems)
-			dict_overwrite(caches["models"], read_attribute(core, elem, "name"), elem)
-			if (value_eq(name, read_attribute(core, elem, "name"))):
-				return elem!
-	else:
-		return current!
+	elems = allAssociationDestinations(core, current, "contains")
+	while (set_len(elems) > 0):
+		elem = set_pop(elems)
+		dict_overwrite(caches["models"], read_attribute(core, elem, "name"), elem)
+		if (value_eq(name, read_attribute(core, elem, "name"))):
+			return elem!
 
 	return ""!
 
@@ -384,7 +385,7 @@ String function export_typing(model : Element, name : String):
 
 	// Create type mapping model
 	String location
-	location = "type mappings/" + cast_id2s(get_type_mapping(model))
+	location = "type mappings/" + cast_id(get_type_mapping(model))
 	export_node(location, get_type_mapping(model))
 
 	String instance_of
@@ -405,7 +406,7 @@ Void function model_create(model : Element, name : String, type_id : String, kin
 	String instance_of
 
 	// Create model itself
-	location = "models/" + cast_id2s(model)
+	location = "models/" + cast_id(model)
 	export_node(location, model["model"])
 
 	model_id = instantiate_node(core, kind, "")
@@ -428,7 +429,7 @@ Void function model_overwrite(model : Element, model_id : String, metamodel_id :
 	String location
 	String instanceOf_link
 
-	location = "models/" + cast_id2s(model)
+	location = "models/" + cast_id(model)
 	export_node(location, model["model"])
 
 	// Change location in meta-data
@@ -464,20 +465,6 @@ Boolean function check_conformance(model_id : String):
 
 	return True!
 
-Boolean function pm_finished(worklist : Element, pm : String):
-	Element finished
-	Integer cnt
-	Integer i
-	// Check if any of the "finish" elements are in the worklist
-	// If so, we can already finish, and therefore will stop immediately
-	finished = allInstances(pm, "Finish")
-	worklist = set_copy(worklist)
-	while (set_len(worklist) > 0):
-		// Check each finished element individually
-		if (set_in(finished, list_read(set_pop(worklist), 0))):
-			return True!
-	return False!
-
 Element function merge_models(models_dict : Element, operation_name : String):
 	core = import_node(core_model_location)
 	// 0) Find operation signature
@@ -641,7 +628,7 @@ Element function execute_operation(operation_id : String, input_models : Element
 	while (set_len(iter) > 0):
 		edge = set_pop(iter)
 		dict_add(output_metamodels, read_attribute(core, edge, "name"), full_name(readAssociationDestination(core, edge)))
-	
+
 	// 1) Find merged metamodel
 
 	exact_type = read_type(core, operation_id)
@@ -660,6 +647,9 @@ Element function execute_operation(operation_id : String, input_models : Element
 		while (set_len(keys) > 0):
 			key = set_pop(keys)
 			Element mm
+			if (get_entry_id(input_models[key]) == ""):
+				// Input model doesn't exist yet, so create
+				cmd_model_add(input_metamodels[key], input_models[key], "")
 			mm = get_full_model(get_entry_id(input_models[key]), get_entry_id(input_metamodels[key]))
 			if (element_eq(mm, read_root())):
 				log("Signature mismatch in operation for tag " + key)
@@ -681,8 +671,8 @@ Element function execute_operation(operation_id : String, input_models : Element
 			Element m
 			m = get_full_model(get_entry_id(input_models[set_pop(dict_keys(input_models))]), get_entry_id(input_metamodels[set_pop(dict_keys(input_metamodels))]))
 			if (element_eq(m, read_root())):
-				log("Signature mismatch in operation for tag " + cast_v2s(set_pop(dict_keys(input_models))))
-				output("Signature mismatch in operation for tag " + cast_v2s(set_pop(dict_keys(input_models))))
+				log("Signature mismatch in operation for tag " + cast_value(set_pop(dict_keys(input_models))))
+				output("Signature mismatch in operation for tag " + cast_value(set_pop(dict_keys(input_models))))
 				return read_root()!
 			merged_model = model_copy(m)
 		elif (bool_and(dict_len(input_models) == 0, dict_len(output_metamodels) == 0)):
@@ -710,8 +700,16 @@ Element function execute_operation(operation_id : String, input_models : Element
 			return read_root()!
 		result = transform(merged_model, operation)
 	elif (exact_type == "ManualOperation"):
-		output("Please perform manual operation " + cast_v2s(full_name(operation_id)))
-		modify(merged_model, True)
+		output("Please perform manual operation " + cast_value(full_name(operation_id)))
+		String model_name
+		model_name = ""
+		while (get_entry_id(model_name) != ""):
+			model_name = ".tmp/" + random_string(20)
+		model_create(merged_model, model_name, merged_metamodel_id, "Model")
+		// We want to modify, so modify
+		do_spawn_modify(model_name, True)
+		merged_model = get_full_model(get_entry_id(model_name), merged_metamodel_id)
+		//model_delete(get_entry_id(model_name))
 		result = True
 	elif (exact_type == "ActionLanguage"):
 		Element func
@@ -763,7 +761,7 @@ Element function execute_operation(operation_id : String, input_models : Element
 		log("Negative result of execution")
 		return read_root()!
 
-Boolean function enact_action(pm : Element, element : String, prefix : String):
+Boolean function enact_action(pm : Element, element : String, mapping : Element):
 	Boolean result
 	String transformation_id
 	Element lst
@@ -776,17 +774,22 @@ Boolean function enact_action(pm : Element, element : String, prefix : String):
 	Element output_mms
 	Element consumes_link
 	String name
-	String value
 	String elem_name
 	Element keys
 	String key
 	String consume
 	String produce
+	Element input_traceability_model
+	String output_traceability_name
+	String output_traceability_type
 	Element output_map
 
 	inputs = dict_create()
 	outputs = dict_create()
 	output_map = dict_create()
+	input_traceability_model = read_root()
+	output_traceability_name = read_root()
+	output_traceability_type = read_root()
 
 	// Read out the referenced element from the MvC
 	transformation_id = get_entry_id(read_attribute(pm, element, "name"))
@@ -795,8 +798,14 @@ Boolean function enact_action(pm : Element, element : String, prefix : String):
 	lst = allOutgoingAssociationInstances(pm, element, "Consumes")
 	while (set_len(lst) > 0):
 		consume = set_pop(lst)
-		value = read_attribute(pm, readAssociationDestination(pm, consume), "name")
-		dict_add(inputs, read_attribute(pm, consume, "name"), prefix + value)
+		elem = readAssociationDestination(pm, consume)
+		type_name = read_attribute(pm, elem, "type")
+		elem_name = read_attribute(pm, elem, "name")
+		if (cast_string(read_attribute(pm, consume, "name")) == "__traceability"):
+			input_traceability_model = model_copy(get_full_model(get_entry_id(mapping[elem_name]), get_entry_id(type_name)))
+			output_traceability_type = type_name
+		else:
+			dict_add(inputs, read_attribute(pm, consume, "name"), mapping[elem_name])
 
 	// Find all output model names and their metamodel
 	lst = allOutgoingAssociationInstances(pm, element, "Produces")
@@ -805,26 +814,36 @@ Boolean function enact_action(pm : Element, element : String, prefix : String):
 		elem = readAssociationDestination(pm, produce)
 		type_name = read_attribute(pm, elem, "type")
 		elem_name = read_attribute(pm, elem, "name")
-		dict_add(outputs, read_attribute(pm, produce, "name"), type_name)
-		dict_add(output_map, read_attribute(pm, produce, "name"), prefix + elem_name)
+		if (cast_string(read_attribute(pm, produce, "name")) == "__traceability"):
+			output_traceability_name = mapping[elem_name]
+		else:
+			dict_add(outputs, read_attribute(pm, produce, "name"), type_name)
+			dict_add(output_map, read_attribute(pm, produce, "name"), mapping[elem_name])
 
 	if read_type(core, transformation_id) == "ActionLanguage":
 		log(string_join("Enacting ActionLanguage: ", read_attribute(pm, element, "name")))
-		output(string_join("Enacting ActionLanguage: ", read_attribute(pm, element, "name")))
+		output("Success: ready for AL execution")
 	elif read_type(core, transformation_id) == "ManualOperation":
 		log(string_join("Enacting ManualOperation: ", read_attribute(pm, element, "name")))
-		output(string_join("Enacting ManualOperation: ", read_attribute(pm, element, "name")))
+		output("Success: ready for MANUAL execution")
 	else:
 		log(string_join("Enacting ModelTransformation: ", read_attribute(pm, element, "name")))
-		output(string_join("Enacting ModelTransformation: ", read_attribute(pm, element, "name")))
-		
-	result = execute_operation(transformation_id, inputs, read_root())
+		output("Success: ready for MT execution")
+
+	result = execute_operation(transformation_id, inputs, input_traceability_model)
 
 	if (element_eq(result, read_root())):
 		// Something went wrong!
+		output("Failure")
 		return False!
 	else:
-		keys = dict_keys(result)
+		// Check if we have to store traceability information
+		if (element_neq(output_traceability_name, read_root())):
+			// Yes, so store it
+			// Note that we have overwritten the previous input traceability model, which is why it was a copy
+			model_overwrite(input_traceability_model, get_entry_id(output_traceability_name), get_entry_id(output_traceability_type))
+
+		keys = dict_keys(outputs)
 		while (set_len(keys) > 0):
 			key = set_pop(keys)
 			if (get_entry_id(output_map[key]) == ""):
@@ -832,9 +851,35 @@ Boolean function enact_action(pm : Element, element : String, prefix : String):
 				model_create(result[key], output_map[key], get_entry_id(outputs[key]), "Model")
 			else:
 				model_overwrite(result[key], get_entry_id(output_map[key]), get_entry_id(outputs[key]))
+		output("Success")
 		return True!
 
-Void function enact_PM(pm : Element, prefix : String):
+Element function PM_signature(pm : Element):
+	Element all_data
+	Element result
+	String entry
+
+	result = dict_create()
+	all_data = allInstances(pm, "Data")
+	while (set_len(all_data) > 0):
+		entry = set_pop(all_data)
+		dict_add(result, cast_string(read_attribute(pm, entry, "name")), cast_string(read_attribute(pm, entry, "type")))
+
+	return result!
+
+Void function enact_PM_activity(activity_to_task : Element, task_to_result : Element, pm : Element, element : String, mapping : Element):
+	Boolean result
+	pm_tasks = activity_to_task
+	set_add(activity_to_task[element], get_taskname())
+	result = enact_action(pm, element, mapping)
+	dict_add_fast(task_to_result, get_taskname(), result)
+
+	while (other_has_output(get_taskname())):
+		sleep(1)
+
+	return!
+
+Void function enact_PM(pm : Element, mapping : Element):
 	Element worklist
 	String element
 	String type
@@ -842,85 +887,151 @@ Void function enact_PM(pm : Element, prefix : String):
 	Element tuple
 	Element counters
 	Element join_nodes
+	Element exec_nodes
+	Element keys
+	String key
 
 	output("Success")
 
+	// For all entries in the signature, not in the mapping, we add a mock location
+	Element signature
+	String mock_location
+	Element mock_locations
+	mock_locations = set_create()
+	signature = PM_signature(pm)
+	keys = dict_keys(signature)
+	while (set_len(keys) > 0):
+		key = set_pop(keys)
+		if (bool_not(dict_in(mapping, key))):
+			// Add mock location
+			mock_location = ""
+			while (get_entry_id(mock_location) != ""):
+				mock_location = ".tmp/" + random_string(10)
+			dict_add(mapping, key, mock_location)
+			cmd_model_add(signature[key], mapping[key], "")
+			set_add(mock_locations, mock_location)
+
 	// Initialize Join counters
 	counters = dict_create()
 	join_nodes = allInstances(pm, "Join")
 	while (set_len(join_nodes) > 0):
 		dict_add(counters, set_pop(join_nodes), 0)
 
+	// Initialize activity to task dictionary with empty sets
+	Element activity_to_task
+	Element task_to_activity
+	Element task_to_result
+
+	activity_to_task = dict_create()
+	task_to_activity = dict_create()
+	task_to_result = dict_create()
+	exec_nodes = allInstances(pm, "Exec")
+	while (set_len(exec_nodes) > 0):
+		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_node(worklist, create_tuple(set_pop(allInstances(pm, "Start")), True))
-
-	while (bool_not(pm_finished(worklist, pm))):
-		// Pop a random element from the list and execute it
-		tuple = set_pop(worklist)
-		element = tuple[0]
-		result = tuple[1]
-
-		// Find the type (to see what to do with it)
-		//   this does not yet yield the type of transformation, if it is an Execution
-		type = read_type(pm, element)
-
-		if (type == "Start"):
-			// Initial node, just progress to the next elements
-			// Nothing to do here though, as we have just started
-			result = True
-		elif (type == "Finish"):
-			// Should be impossible, as we would have ended...
-			result = result
-		elif (type == "Fork"):
-			result = result
-		elif (type == "Join"):
-			// Only do this if all dependencies are fullfilled
-			// So add to the counter of this Join
-			dict_overwrite(counters, element, integer_addition(counters[element], 1))
-
-			// 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"))
-			got = counters[element]
-			if (got == required):
-				// Reset counter to 0
-				dict_overwrite(counters, element, 0)
-
-				// And continue
-			else:
-				// We haven't gotten all yet, so we wait (i.e., continue without adding Next link to worklist)
-				continue!
+	set_add(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):
+			// There is something we can do, so do it!
+			element = set_pop(worklist)
 
-		elif (type == "Exec"):
-			// Execute a transformation
-			// This the difficult part!
+			// Find the type (to see what to do with it)
+			//   this does not yet yield the type of transformation, if it is an Execution
+			type = read_type(pm, element)
 
-			result = enact_action(pm, element, prefix)
-			output("Success")
+			// Some types have nothing to do, such as start and fork
+			// Therefore, they are not mentioned in the following conditional
 
-		elif (type == "Decision"):
-			// If the previous result is true, we add the normal one, otherwise the false one
-			// in this context, that means that if it is false, we should add it manually to the list, and then continue the simulation loop
-			if (bool_not(result)):
-				// Apparently it is False, so map this to the "Else" branch
-				set_add_node(worklist, create_tuple(set_pop(allAssociationDestinations(pm, element, "Else")), True))
+			if (type == "Finish"):
+				// We have finished, so terminate
+				break!
+			elif (type == "Join"):
+				// Only do this if all dependencies are fullfilled
+				// So add to the counter of this Join
+				dict_overwrite(counters, element, integer_addition(counters[element], 1))
+
+				// 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"))
+				got = counters[element]
+				if (got == required):
+					// Reset counter to 0
+					dict_overwrite(counters, element, 0)
+
+					// And continue
+				else:
+					// We haven't gotten all yet, so we wait (i.e., continue without adding Next link to worklist)
+					continue!
+
+			elif (type == "Exec"):
+				// Execute a transformation
+				// This the difficult part!
+
+				Element args
+				String taskname
+				args = list_create()
+				list_append(args, activity_to_task)
+				list_append(args, task_to_result)
+				list_append(args, pm)
+				list_append(args, element)
+				list_append(args, mapping)
+				taskname = spawn(enact_PM_activity, args)
+				output(taskname + " : " + cast_string(read_attribute(pm, element, "name")))
+				dict_add(task_to_activity, taskname, element)
 				continue!
+
+			// We have finished the execution, so add all outgoing edges to the worklist
+			Element all_next
+			all_next = allAssociationDestinations(pm, element, "Next")
+			String next
+			while (set_len(all_next) > 0):
+				next = set_pop(all_next)
+				set_add(worklist, next)
+		else:
+			// No new tasks to spawn, so go and check on all running activities
+			if (dict_len(task_to_result) > 0):
+				// There are outputs!
+				Element keys
+				String task
+
+				keys = dict_keys(task_to_result)
+				while (set_len(keys) > 0):
+					task = set_pop(keys)
+					result = task_to_result[task]
+
+					Element all_next
+					all_next = allAssociationDestinations(pm, task_to_activity[task], "Next")
+					String next
+					while (set_len(all_next) > 0):
+						next = set_pop(all_next)
+
+						if (read_type(pm, next) == "Decision"):
+							// Got decision node, so expand immediately
+							if (result):
+								set_add(worklist, set_pop(allAssociationDestinations(pm, next, "Then")))
+							else:
+								set_add(worklist, set_pop(allAssociationDestinations(pm, next, "Else")))
+						else:
+							// Other node, so just append for further processing
+							set_add(worklist, next)
+
+					set_remove(activity_to_task[task_to_activity[task]], task)
+					dict_delete(task_to_result, task)
+					dict_delete(task_to_activity, task)
 			else:
-				// Apparently it is True, so map this to the "Then" branch
-				set_add_node(worklist, create_tuple(set_pop(allAssociationDestinations(pm, element, "Then")), True))
-				continue!
+				// No finished activities either, so we sleep for some time
+				sleep(0.1)
 
-		// We have finished the execution, so add all outgoing edges to the worklist
-		Element all_next
-		all_next = allAssociationDestinations(pm, element, "Next")
-		String next
-		while (set_len(all_next) > 0):
-			next = set_pop(all_next)
-			set_add_node(worklist, create_tuple(next, result))
+	// Remove all mock locations again
+	while (set_len(mock_locations) > 0):
+		model_delete(get_entry_id(set_pop(mock_locations)))
 
-	// Reached a finish element, so stop
 	return !
 
 String function cmd_help():
@@ -988,36 +1099,31 @@ String function cmd_model_add(type : String, name : String, code : String):
 		// Type exists
 		if (allow_read(current_user_id, type_id)):
 			// And is readable
-			if (get_entry_id(get_foldername(name)) != ""):
-				// Folder doesn't exist yet!
-				if (allow_write(current_user_id, get_entry_id(get_foldername(name)))):
-					// Folder is writable
-					if (get_entry_id(name) == ""):
-						// Model doesn't exist yet
-						Element mm
-						mm = get_full_model(type_id, get_entry_id("formalisms/SimpleClassDiagrams"))
-						if (element_eq(mm, read_root())):
-							return "Type is not typed by formalisms/SimpleClassDiagrams: " + type!
+			create_folders(current_user_id, get_foldername(name))
+			//TODO check if bottommost existing model was writable by us
+
+			if (get_entry_id(name) == ""):
+				// Model doesn't exist yet
+				Element mm
+				mm = get_full_model(type_id, get_entry_id("formalisms/SimpleClassDiagrams"))
+				if (element_eq(mm, read_root())):
+					return "Type is not typed by formalisms/SimpleClassDiagrams: " + type!
 
-						new_model = compile_model(code, mm)
+				new_model = compile_model(code, mm)
 
-						if (element_eq(new_model, read_root())):
-							return "Compilation error"!
+				if (element_eq(new_model, read_root())):
+					return "Compilation error"!
 
-						model_create(new_model, name, type_id, "Model")
-						return "Success"!
-					else:
-						return "Model exists: " + name!
-				else:
-					return "Permission denied to folder: " + get_foldername(name)!
+				model_create(new_model, name, type_id, "Model")
+				return "Success"!
 			else:
-				return "No such folder: " + get_foldername(name)!
+				return "Model exists: " + name!
 		else:
 			return "Permission denied to model: " + type!
 	else:
 		return "Model not found: " + type!
 
-String function cmd_process_execute(process : String, prefix : String):
+String function cmd_process_execute(process : String, mapping : Element):
 	// Execute a process model until it reaches termination
 	String process_id
 
@@ -1029,13 +1135,42 @@ String function cmd_process_execute(process : String, prefix : String):
 			if (element_eq(pm, read_root())):
 				return "Specified model cannot be interpreted as a ProcessModel: " + process!
 
-			enact_PM(pm, prefix)
+			enact_PM(pm, mapping)
 			return "Success"!
 		else:
 			return "Permission denied to model: " + process!
 	else:
 		return "Model not found: " + process!
 
+String function cmd_process_signature(process : String):
+	// Execute a process model until it reaches termination
+	String process_id
+	String result
+	Element signature
+	Element keys
+	String key
+
+	process_id = get_entry_id(process)
+	if (process_id != ""):
+		if (allow_read(current_user_id, process_id)):
+			Element pm
+			pm = get_full_model(process_id, get_entry_id("formalisms/ProcessModel"))
+			if (element_eq(pm, read_root())):
+				return "Specified model cannot be interpreted as a ProcessModel: " + process!
+
+			result = "Success: "
+			signature = PM_signature(pm)
+			keys = dict_keys(signature)
+			while (set_len(keys) > 0):
+				key = set_pop(keys)
+				result = result + key + " : " + cast_string(signature[key]) + "\n"
+
+			return result!
+		else:
+			return "Permission denied to model: " + process!
+	else:
+		return "Model not found: " + process!
+
 String function cmd_transformation_between(source_dict : String, target_dict : String):
 	Element result
 	Element subresult
@@ -1046,7 +1181,6 @@ String function cmd_transformation_between(source_dict : String, target_dict : S
 	String link
 	Element keys
 
-	log("Finding transformation from " + dict_to_string(source_dict) + " to " + dict_to_string(target_dict))
 	result = allInstances(core, "Transformation")
 
 	// Iterate over all inputs
@@ -1099,7 +1233,6 @@ String function cmd_transformation_between(source_dict : String, target_dict : S
 		transformation = set_pop(result)
 		if (allow_read(current_user_id, transformation)):
 			r = r + string_join(full_name(transformation), "\n")
-			log("Found: " + full_name(transformation))
 	return r!
 
 String function cmd_model_rendered(model_name : String, mapper_name : String):
@@ -1228,12 +1361,89 @@ String function cmd_model_render(model_name : String, mapper_name : String, rend
 	else:
 		return "Model not found: " + model_name!
 
-	//trace_links = allOutgoingAssociationInstances(core, operation_id, "tracability")
-	//merged_metamodel_id = ""
-	//while (set_len(trace_links) > 0):
-	//	trace_link_id = set_pop(trace_links)
-	//	if (value_eq(read_attribute(core, trace_link_id, "type"), "operatesOn")):
-	//		merged_metamodel_id = readAssociationDestination(core, trace_link_id)
+Boolean function do_spawn_modify(model_name : String, write : Boolean):
+	output("Please edit this model before sending next input: " + model_name)
+	input()
+	return False!
+
+Boolean function do_spawn_activity(transformation_id : String, tracability_name : String, inputs : Element, outputs : Element, output_map : Element):
+	Element lst
+	Element returnvalue
+	String taskname
+
+	lst = list_create()
+	returnvalue = set_create()
+	list_append(lst, returnvalue)
+	list_append(lst, transformation_id)
+	list_append(lst, tracability_name)
+	list_append(lst, inputs)
+	list_append(lst, outputs)
+	list_append(lst, output_map)
+	taskname = spawn(spawn_activity, lst)
+
+	output("Spawned activity on task: " + taskname)
+
+	while (set_len(returnvalue) == 0):
+		sleep(0.1)
+
+	output("Finished task: " + taskname)
+	return cast_boolean(set_pop(returnvalue))!
+
+Void function spawn_activity(returnvalue : Element, transformation_id : String, tracability_name : String, inputs : Element, outputs : Element, output_map : Element):
+	Element result
+	Element keys
+	String key
+
+	if (read_type(core, transformation_id) == "ActionLanguage"):
+		output("Success: ready for AL execution")
+	elif (read_type(core, transformation_id) == "ManualOperation"):
+		output("Success: ready for MANUAL execution")
+	else:
+		output("Success: ready for MT execution")
+
+	// Do tracability
+	Element tracability_model
+	if (tracability_name != ""):
+		// Check if exists
+		if (get_entry_id(tracability_name) == ""):
+			// No, so create
+			tracability_model = instantiate_model(get_full_model(get_entry_id("formalisms/Tracability"), get_entry_id("formalisms/SimpleClassDiagrams")))
+			model_create(tracability_model, tracability_name, get_entry_id("formalisms/Tracability"), "Model")
+		else:
+			// Yes, so read out
+			tracability_model = get_full_model(get_entry_id(tracability_name), get_entry_id("formalisms/Tracability"))
+	else:
+		tracability_model = read_root()
+
+	result = execute_operation(transformation_id, inputs, tracability_model)
+
+	// Flush tracability again, just to be sure
+	if (tracability_name != ""):
+		model_overwrite(tracability_model, get_entry_id(tracability_name), get_entry_id("formalisms/Tracability"))
+
+	// Now write out the models again
+	if (element_eq(result, read_root())):
+		// Something went wrong!
+		set_add(returnvalue, False)
+		output("Failure")
+	else:
+		keys = dict_keys(outputs)
+		while (set_len(keys) > 0):
+			key = set_pop(keys)
+			
+			if (get_entry_id(outputs[key]) == ""):
+				// New model
+				model_create(result[key], outputs[key], get_entry_id(output_map[key]), "Model")
+			else:
+				model_overwrite(result[key], get_entry_id(outputs[key]), get_entry_id(output_map[key]))
+
+		set_add(returnvalue, True)
+		output("Success")
+
+	while (other_has_output(get_taskname())):
+		sleep(1)
+
+	return!
 
 String function cmd_transformation_execute(transformation_name : String, source_models : Element, target_models : Element, tracability_name : String):
 	// Execute a transformation, whatever type it is
@@ -1251,9 +1461,6 @@ String function cmd_transformation_execute(transformation_name : String, source_
 	String target_model_name
 	String source_model_name
 	String source_model_ID
-	Element result
-	Element keys
-	String key
 	String assoc_name
 
 	transformation_id = get_entry_id(transformation_name)
@@ -1310,49 +1517,10 @@ String function cmd_transformation_execute(transformation_name : String, source_
 							else:
 								return "Permission denied to model: " + target_model_name!
 
-				if (read_type(core, transformation_id) == "ActionLanguage"):
-					output("Success: ready for AL execution")
-				elif (read_type(core, transformation_id) == "ManualOperation"):
-					output("Success: ready for MANUAL execution")
-				else:
-					output("Success: ready for MT execution")
-
-				// Do tracability
-				Element tracability_model
-				if (tracability_name != ""):
-					// Check if exists
-					if (get_entry_id(tracability_name) == ""):
-						// No, so create
-						tracability_model = instantiate_model(get_full_model(get_entry_id("formalisms/Tracability"), get_entry_id("formalisms/SimpleClassDiagrams")))
-						model_create(tracability_model, tracability_name, get_entry_id("formalisms/Tracability"), "Model")
-					else:
-						// Yes, so read out
-						tracability_model = get_full_model(get_entry_id(tracability_name), get_entry_id("formalisms/Tracability"))
+				if (do_spawn_activity(transformation_id, tracability_name, inputs, outputs, output_map)):
+					return "Success"!
 				else:
-					tracability_model = read_root()
-
-				result = execute_operation(transformation_id, inputs, tracability_model)
-
-				// Flush tracability again, just to be sure
-				if (tracability_name != ""):
-					model_overwrite(tracability_model, get_entry_id(tracability_name), get_entry_id("formalisms/Tracability"))
-
-				// Now write out the models again
-				if (element_eq(result, read_root())):
-					// Something went wrong!
 					return "Failure"!
-				else:
-					keys = dict_keys(result)
-					while (set_len(keys) > 0):
-						key = set_pop(keys)
-						
-						if (get_entry_id(outputs[key]) == ""):
-							// New model
-							model_create(result[key], outputs[key], get_entry_id(output_map[key]), "Model")
-						else:
-							model_overwrite(result[key], get_entry_id(outputs[key]), get_entry_id(output_map[key]))
-
-					return "Success"!
 			else:
 				return "Model is not executable: " + transformation_name!
 		else:
@@ -1611,13 +1779,15 @@ String function transformation_add(source_models : Element, target_models : Elem
 	if (get_entry_id(operation_name) == ""):
 		// Write out a merged metamodel containing all these models: this is the MM for the manual operation
 		// New location is available, so write
-		if (bool_not(bool_and(dict_len(source_models) == 0, dict_len(target_models) == 0))):
+		if (dict_len(source_models) + dict_len(target_models) > 0):
 			merged_formalism = model_fuse(formalism_map)
 			model_create(merged_formalism, "merged/" + operation_name, get_entry_id("formalisms/SimpleClassDiagrams"), "Model")
-			modify(merged_formalism, True)
-			model_overwrite(merged_formalism, get_entry_id("merged/" + operation_name), get_entry_id("formalisms/SimpleClassDiagrams"))
+			do_spawn_modify("merged/" + operation_name, True)
+			merged_formalism = get_full_model(get_entry_id("merged/" + operation_name), get_entry_id("formalisms/SimpleClassDiagrams"))
 
 		if (operation_type == "manual"):
+			if (dict_len(source_models) + dict_len(target_models) == 0):
+				return "Manual activity needs at least one formalism in its input or output signature!"!
 			// Finished with all information, now create the model itself!
 			Element m
 			m = get_full_model(get_entry_id("formalisms/ManualOperation"), get_entry_id("formalisms/SimpleClassDiagrams"))
@@ -1639,7 +1809,7 @@ String function transformation_add(source_models : Element, target_models : Elem
 			model_create(import_node("AL/" + operation_name), operation_name, get_entry_id("formalisms/ActionLanguage"), "ActionLanguage")
 			model_id = get_entry_id(operation_name)
 
-		if (bool_not(bool_and(dict_len(source_models) == 0, dict_len(target_models) == 0))):
+		if (dict_len(source_models) + dict_len(target_models) > 0):
 			merged_formalism_id = get_entry_id("merged/" + operation_name)
 
 			// Add tracability links at this level
@@ -1658,7 +1828,6 @@ String function transformation_add(source_models : Element, target_models : Elem
 			keys = dict_keys(source)
 			while (set_len(keys) > 0):
 				key = set_pop(keys)
-				log("Add transformInput link for " + model_id + " to " + cast_v2s(source[key]) + " while adding operation " + operation_name)
 				link = instantiate_link(core, "transformInput", "", model_id, source[key])
 				instantiate_attribute(core, link, "name", key)
 
@@ -1701,6 +1870,9 @@ String function cmd_transformation_add_MT(source_models : Element, target_models
 	target = dict_create()
 	to_ramify = set_create()
 
+	if (dict_len(source_models) + dict_len(target_models) == 0):
+		return "Model transformation needs at least one formalism in its input or output signature!"!
+
 	keys = dict_keys(source_models)
 	while (set_len(keys) > 0):
 		key = set_pop(keys)
@@ -1756,7 +1928,10 @@ String function cmd_transformation_add_MT(source_models : Element, target_models
 			return "Model not found: " + name!
 
 	merged_formalism = model_fuse(to_ramify)
-	modify(merged_formalism, True)
+	model_create(merged_formalism, "merged/" + operation_name, get_entry_id("formalisms/SimpleClassDiagrams"), "Model")
+	do_spawn_modify("merged/" + operation_name, True)
+	merged_formalism = get_full_model(get_entry_id("merged/" + operation_name), get_entry_id("formalisms/SimpleClassDiagrams"))
+	model_overwrite(merged_formalism, get_entry_id("merged/" + operation_name), get_entry_id("formalisms/SimpleClassDiagrams"))
 
 	ramified_metamodel = ramify(merged_formalism)
 	model_create(ramified_metamodel, "RAMified/" + operation_name, get_entry_id("formalisms/SimpleClassDiagrams"), "Model")
@@ -1794,7 +1969,6 @@ String function cmd_transformation_add_MT(source_models : Element, target_models
 		while (set_len(keys) > 0):
 			key = set_pop(keys)
 			dst = source[key]
-			log("Add transformInput link for " + model_id + " to " + dst + " while adding operation " + operation_name)
 			link = instantiate_link(core, "transformInput", "", model_id, dst)
 			instantiate_attribute(core, link, "name", key)
 
@@ -1823,7 +1997,7 @@ String function cmd_permission_modify(model_name : String, permissions : String)
 				fail = True
 
 			while (i < 3):
-				permission = cast_s2i(string_get(permissions, i))
+				permission = cast_integer(string_get(permissions, i))
 				if (bool_or(permission < 0, permission > 2)):
 					fail = True
 					break!
@@ -2072,7 +2246,7 @@ String function cmd_service_register(service_name : String):
 		output("Success: " + get_taskname())
 
 		// Wait until we can stop the service
-		while (cast_v2s(input()) != "\"service_stop\""):
+		while (cast_value(input()) != "\"service_stop\""):
 			output("Service is running on this task: stop it by sending 'service_stop'")
 
 		model_delete_element(core, service)
@@ -2189,7 +2363,9 @@ Void function user_function_skip_init(user_id : String):
 		elif (cmd == "model_add"):
 			output(cmd_model_add(single_input("Model type?"), single_input("Model name?"), single_input("Model textual representation?")))
 		elif (cmd == "process_execute"):
-			output(cmd_process_execute(single_input("Process to execute?"), single_input("Model prefix to use?")))
+			output(cmd_process_execute(single_input("Process to execute?"), dict_input("Model bindings to use?")))
+		elif (cmd == "process_signature"):
+			output(cmd_process_signature(single_input("Process to execute?")))
 		elif (cmd == "transformation_between"):
 			output(cmd_transformation_between(dict_input("Source signature?"), dict_input("Target signature?")))
 		elif (cmd == "model_render"):
@@ -2213,11 +2389,11 @@ Void function user_function_skip_init(user_id : String):
 		elif (cmd == "model_list_full"):
 			output(cmd_model_list_full(single_input("Location?")))
 		elif (cmd == "transformation_add_MANUAL"):
-			output(cmd_transformation_add_MANUAL(dict_input("Source model names?"), dict_input("Target model names?"), single_input("Operation name?")))
+			output(cmd_transformation_add_MANUAL(dict_input("Source models?"), dict_input("Target models?"), single_input("Operation name?")))
 		elif (cmd == "transformation_add_AL"):
-			output(cmd_transformation_add_AL(dict_input("Source model names?"), dict_input("Target model names?"), single_input("Operation name?")))
+			output(cmd_transformation_add_AL(dict_input("Source models?"), dict_input("Target models?"), single_input("Operation name?")))
 		elif (cmd == "transformation_add_MT"):
-			output(cmd_transformation_add_MT(dict_input("Source model names?"), dict_input("Target models?"), single_input("Operation name?")))
+			output(cmd_transformation_add_MT(dict_input("Source models?"), dict_input("Target models?"), single_input("Operation name?")))
 		elif (cmd == "permission_modify"):
 			output(cmd_permission_modify(single_input("Model name?"), single_input("Permissions?")))
 		elif (cmd == "permission_owner"):
@@ -2267,7 +2443,6 @@ Void function user_function_skip_init(user_id : String):
 		elif (cmd == "folder_create"):
 			output(cmd_folder_create(single_input("Folder name?")))
 		elif (cmd == "add_conformance"):
-			// TODO
 			output(cmd_conformance_add(single_input("Model name?"), single_input("Metamodel name?")))
 		elif (cmd == "remove_conformance"):
 			// TODO

+ 25 - 0
bootstrap/files.alc

@@ -0,0 +1,25 @@
+include "primitives.alh"
+include "services.alh"
+
+String function files_connect():
+	String port
+	port = ""
+	while (port == ""):
+		port = comm_connect("files")
+	return port!
+
+Boolean function write_file(filename : String, content : String):
+	String port
+	String result
+
+	port = files_connect()
+	comm_set(port, filename)
+	comm_set(port, content)
+
+	result = comm_get(port)
+	comm_close(port)
+	if result == "Success":
+		return True!
+	else:
+		log("Error in writing to file: " + result)
+		return False!

+ 1 - 0
bootstrap/initial_code_task.alc

@@ -25,5 +25,6 @@ Void mutable function __main():
 	exec(root["bootstrap/typing.alc"]["initializers"])
 	exec(root["bootstrap/compiler.alc"]["initializers"])
 	exec(root["bootstrap/json.alc"]["initializers"])
+	exec(root["bootstrap/files.alc"]["initializers"])
 	new_task()
 	return!

+ 32 - 0
bootstrap/io.alc

@@ -34,3 +34,35 @@ Element function input_timeout(timeout : Float):
 			interruptable_sleep(0.1)
 
 	return read_root()!
+
+Boolean function other_has_output(comm : String):
+	// Check if there is any input on the specified pseudo-username
+	Element root
+	root = read_root()
+	return dict_in(root[comm]["output"], "value")!
+
+Void function give_input_to_other(comm : String, value : Element):
+	Element root
+	root = read_root()
+
+	Element new
+	new = create_node()
+	dict_add(root[comm]["last_input"], "value", value)
+	dict_add(root[comm]["last_input"], "next", new)
+	dict_overwrite(root[comm], "last_input", new)
+
+	return!
+
+Element function get_output_from_other(comm : String):
+	// Fetch input from the service
+	while (bool_not(other_has_output(comm))):
+		sleep(0.1)
+
+	// Return the value that we got
+	Element root
+	Element value
+	root = read_root()
+	value = root[comm]["output"]["value"]
+	dict_overwrite(root[comm], "output", root[comm]["output"]["next"])
+
+	return value!

+ 12 - 12
bootstrap/mini_modify.alc

@@ -40,7 +40,7 @@ String function pretty_print(model : Element):
 			attr_keys = dict_keys(attr_list)
 			while (set_len(attr_keys) > 0):
 				attr_key = set_pop(attr_keys)
-				result = result + "      " + attr_key + " : " + cast_v2s(attr_list[attr_key])
+				result = result + "      " + attr_key + " : " + cast_value(attr_list[attr_key])
 				result = result + "\n"
 
 			// Has attributes
@@ -49,9 +49,9 @@ String function pretty_print(model : Element):
 			while (set_len(attr_keys) > 0):
 				attr_key = set_pop(attr_keys)
 				if (element_eq(read_attribute(model, v_m, attr_key), read_root())):
-					result = result + "      " + cast_v2s(attr_key) + " : " + cast_v2s(attr_list[attr_key]) + " = (undefined)"
+					result = result + "      " + cast_string(attr_key) + " : " + cast_string(attr_list[attr_key]) + " = (undefined)"
 				else:
-					result = result + "      " + cast_v2s(attr_key) + " : " + cast_v2s(attr_list[attr_key]) + " = " + cast_v2s(read_attribute(model, v_m, attr_key))
+					result = result + "      " + cast_string(attr_key) + " : " + cast_string(attr_list[attr_key]) + " = " + cast_value(read_attribute(model, v_m, attr_key))
 				result = result + "\n"
 		else:
 			log("Skip instance: " + type)
@@ -264,7 +264,6 @@ String function cmd_attr_optional(write : Boolean, model : Element, element_name
 				if (set_in(dict_keys(attrs), attr_name)):
 					String attr_edge
 					attr_edge = reverseKeyLookup(model["model"], dict_read_edge(model["model"][element_name], attr_name))
-					log("Was optional: " + cast_v2s(read_attribute(model, attr_edge, "optional")))
 					if (optional):
 						log("Setting to optional")
 					else:
@@ -398,7 +397,7 @@ String function cmd_read(model : Element, element_name : String):
 			result = result + "Source: " + reverseKeyLookup(model["model"], read_edge_src(model["model"][element_name])) + "\n"
 			result = result + "Destination: " + reverseKeyLookup(model["model"], read_edge_dst(model["model"][element_name])) + "\n"
 		if (has_value(model["model"][element_name])):
-			result = result + "Value: " + cast_v2s(model["model"][element_name]) + "\n"
+			result = result + "Value: " + cast_value(model["model"][element_name]) + "\n"
 		return result!
 	else:
 		return "Element not found: " + element_name!
@@ -415,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_v2s(attr_list[attr_key]) + " = " + cast_v2s(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!
@@ -433,9 +432,9 @@ String function cmd_read_defined_attrs(model : Element, element_name : String):
 		while (0 < set_len(attr_keys)):
 			attr_key = set_pop(attr_keys)
 			if (value_eq(read_attribute(model, reverseKeyLookup(model["model"], dict_read_edge(model["model"][element_name], attr_key)), "optional"), True)):
-				result = string_join(result, attr_key) + " ?: " + cast_v2s(attr_list[attr_key]) + "\n"
+				result = string_join(result, attr_key) + " ?: " + cast_value(attr_list[attr_key]) + "\n"
 			else:
-				result = string_join(result, attr_key) + " : " + cast_v2s(attr_list[attr_key]) + "\n"
+				result = string_join(result, attr_key) + " : " + cast_value(attr_list[attr_key]) + "\n"
 		return result!
 	else:
 		return "Element not found: " + element_name!
@@ -498,7 +497,7 @@ String function cmd_all_instances(model : Element, type : String):
 	else:
 		return "Element not found: " + type!
 
-Element function modify(model : Element, write : Boolean):
+Boolean function modify(model : Element, write : Boolean):
 	String cmd
 
 	output("Model loaded, ready for commands!")
@@ -508,7 +507,9 @@ Element function modify(model : Element, write : Boolean):
 		if (cmd == "help"):
 			output(cmd_help_m(write))
 		elif (cmd == "exit"):
-			return model!
+			return True!
+		elif (cmd == "drop"):
+			return False!
 		elif (cmd == "upload"):
 			output(cmd_upload(write, model))
 		elif (cmd == "instantiate_node"):
@@ -564,9 +565,8 @@ Element function modify(model : Element, write : Boolean):
 		elif (cmd == "undefine_attribute"):
 			output(cmd_undefine_attribute(write, model, single_input("On which element?"), single_input("Attribute name?")))
 		else:
-			output("Unknown command while modelling: " + cmd)
+			output("Unknown command while modelling: " + cast_value(cmd))
 			output("Use command 'help' to get a list of available commands")
-	return model!
 
 String function single_input(prompt : String):
 	if (verbose):

+ 19 - 16
bootstrap/model_management.alc

@@ -5,6 +5,7 @@ include "constructors.alh"
 include "metamodels.alh"
 include "library.alh"
 include "modelling.alh"
+include "utils.alh"
 
 Element function model_fuse(models : Element):
 	Element new_model
@@ -45,8 +46,8 @@ Element function model_fuse(models : Element):
 			if (is_edge(model["model"][key])):
 				String src
 				String dst
-				src = string_join(model_name, reverse[cast_id2s(read_edge_src(model["model"][key]))])
-				dst = string_join(model_name, reverse[cast_id2s(read_edge_dst(model["model"][key]))])
+				src = string_join(model_name, reverse[cast_id(read_edge_src(model["model"][key]))])
+				dst = string_join(model_name, reverse[cast_id(read_edge_dst(model["model"][key]))])
 				if (bool_and(dict_in(new_model["model"], src), dict_in(new_model["model"], dst))):
 					instantiate_link(new_model, type, model_name + key, src, dst)
 				else:
@@ -84,8 +85,8 @@ Element function model_copy(src_model : Element):
 			String src
 			String dst
 
-			src = reverse[cast_id2s(read_edge_src(src_model["model"][name]))]
-			dst = reverse[cast_id2s(read_edge_dst(src_model["model"][name]))]
+			src = reverse[cast_id(read_edge_src(src_model["model"][name]))]
+			dst = reverse[cast_id(read_edge_dst(src_model["model"][name]))]
 
 			type = read_type(src_model, name)
 
@@ -150,8 +151,8 @@ Element function model_join(models : Element, metamodel : Element, tracability_m
 			new_name = retyping_key + key
 
 			if (is_edge(model["model"][key])):
-				src = cast_id2s(read_edge_src(model["model"][key]))
-				dst = cast_id2s(read_edge_dst(model["model"][key]))
+				src = cast_id(read_edge_src(model["model"][key]))
+				dst = cast_id(read_edge_dst(model["model"][key]))
 				if (bool_and(dict_in(elem_map, src), dict_in(elem_map, dst))):
 					new_name = instantiate_link(new_model, retyping_key + type, new_name, elem_map[src], elem_map[dst])
 				else:
@@ -164,7 +165,7 @@ Element function model_join(models : Element, metamodel : Element, tracability_m
 
 			if (new_name != ""):
 				// Add the new name to a map which registers the mapping to the new name
-				dict_add_fast(elem_map, cast_id2s(model["model"][key]), new_name)
+				dict_add_fast(elem_map, cast_id(model["model"][key]), new_name)
 
 			if (set_len(keys) == 0):
 				keys = second_keys
@@ -192,6 +193,7 @@ Element function model_join(models : Element, metamodel : Element, tracability_m
 
 			src_name = read_attribute(tracability_model, readAssociationSource(tracability_model, tracability_link), "name")
 			dst_name = read_attribute(tracability_model, readAssociationDestination(tracability_model, tracability_link), "name")
+
 			type = read_attribute(tracability_model, tracability_link, "type")
 
 			// Now try to find all possible combinations
@@ -210,6 +212,7 @@ Element function model_join(models : Element, metamodel : Element, tracability_m
 						if (dict_in(new_model["model"], dst_model + dst_name)):
 							// 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")
 	return new_model!
@@ -260,7 +263,7 @@ Element function model_split(merged_model : Element, models : Element, tracabili
 		key = set_pop(keys)
 		elem = merged_model["model"][key]
 		type = read_type(merged_model, key)
-		splitted = string_split(type, "/")
+		splitted = string_split_nr(type, "/", 1)
 
 		if (list_len(splitted) == 1):
 			// Only one, so no split possible
@@ -269,12 +272,12 @@ Element function model_split(merged_model : Element, models : Element, tracabili
 				// Got a tracability link!
 				// Is always an edge (for now?)
 				// Find out source and target and hope that they are already present
-				src = reverse[cast_id2s(read_edge_src(elem))]
-				dst = reverse[cast_id2s(read_edge_dst(elem))]
+				src = reverse[cast_id(read_edge_src(elem))]
+				dst = reverse[cast_id(read_edge_dst(elem))]
 
 				// All present, so create the link between them
-				src_name = list_pop_final(string_split(src, "/"))
-				dst_name = list_pop_final(string_split(dst, "/"))
+				src_name = list_pop_final(string_split_nr(src, "/", 1))
+				dst_name = list_pop_final(string_split_nr(dst, "/", 1))
 
 				source = instantiate_node(tracability_model, "Reference", "")
 				target = instantiate_node(tracability_model, "Reference", "")
@@ -286,7 +289,7 @@ Element function model_split(merged_model : Element, models : Element, tracabili
 		else:
 			retyping_key = splitted[0]
 			if (list_len(string_split(key, "/")) > 1):
-				new_name = list_read(string_split(key, "/"), 1)
+				new_name = list_read(string_split_nr(key, "/", 1), 1)
 			else:
 				new_name = key
 
@@ -295,8 +298,8 @@ Element function model_split(merged_model : Element, models : Element, tracabili
 
 				if (is_edge(elem)):
 					// Is an edge, so potentially queue it
-					src = reverse[cast_id2s(read_edge_src(elem))]
-					dst = reverse[cast_id2s(read_edge_dst(elem))]
+					src = reverse[cast_id(read_edge_src(elem))]
+					dst = reverse[cast_id(read_edge_dst(elem))]
 
 					if (bool_and(dict_in(mapping, src), dict_in(mapping, dst))):
 						// All present, so create the link between them
@@ -325,6 +328,6 @@ Element function model_split(merged_model : Element, models : Element, tracabili
 	// Finally, we also add tracability information as a separate model
 	if (tracability):
 		dict_add_fast(result, "__tracability", tracability_model)
-		log("Tracability model created with # links = " + cast_v2s(dict_len(tracability_model["model"])))
+		log("Tracability model created with # links = " + cast_value(dict_len(tracability_model["model"])))
 
 	return result!

+ 16 - 11
bootstrap/modelling.alc

@@ -11,7 +11,7 @@ Element global_models = ?
 
 String function instantiated_name(element : Element, original : String):
 	if (original == ""):
-		return "__" + cast_id2s(element)!
+		return "__" + cast_id(element)!
 	else:
 		return original!
 
@@ -268,7 +268,7 @@ Void function instantiate_attribute_ref(model : Element, element : String, attri
 	attr_type = find_attribute_type(model, element, attribute_name)
 
 	if (attr_type == ""):
-		log("Could not find attribute " + cast_v2s(attribute_name))
+		log("Could not find attribute " + cast_value(attribute_name))
 		return!
 		
 	instantiate_link(model, attr_type, "", element, ref)
@@ -286,7 +286,7 @@ Void function add_code_model(model : Element, export_name : String, code : Eleme
 Void function instantiate_attribute_code(model : Element, element : String, attribute_name : String, code : Element):
 	// First create a new model for the AL part
 	String location
-	location = "code/" + cast_id2s(code)
+	location = "code/" + cast_id(code)
 
 	add_code_model(import_node("models/ActionLanguage"), location, code)
 
@@ -304,7 +304,7 @@ Void function instantiate_existing_attribute(model : Element, element : String,
 	attr_type = find_attribute_type(model, element, attribute_name)
 
 	if (attr_type == ""):
-		log("Could not find attribute " + cast_v2s(attribute_name))
+		log("Could not find attribute " + cast_value(attribute_name))
 		return!
 		
 	// Make a copy of the value, as it is likely that this value is reused later on
@@ -391,7 +391,7 @@ String function model_define_attribute(model : Element, elem : String, name : St
 	edge_name = (elem + "_") + name
 	while (dict_in(model["model"], edge_name)):
 		// Already exists, so make random name
-		edge_name = edge_name + cast_id2s(model["model"][elem])
+		edge_name = edge_name + cast_id(model["model"][elem])
 		log("Name clash detected for attribute: try new name: " + edge_name)
 
 	edge_name = instantiate_link(model, "AttributeLink", edge_name, elem, type)
@@ -407,7 +407,7 @@ String function model_define_attribute_ID(model : Element, elem : String, name :
 	edge_name = ID
 	while (dict_in(model["model"], edge_name)):
 		// Already exists, so make random name
-		edge_name = edge_name + cast_id2s(model["model"][elem])
+		edge_name = edge_name + cast_id(model["model"][elem])
 		log("Name clash detected for attribute: try new name: " + edge_name)
 
 	edge_name = instantiate_link(model, "AttributeLink", edge_name, elem, type)
@@ -449,15 +449,20 @@ Void function unset_attribute(model : Element, element : String, attribute : Str
 	String attr_type
 	Element attr_links
 	String attr_link
+	String attr_value
 	
 	attr_type = find_attribute_type(model, element, attribute)
 	attr_links = allOutgoingAssociationInstances(model, element, attr_type)
 
 	while (set_len(attr_links) > 0):
 		attr_link = set_pop(attr_links)
-		remove_type(model, reverseKeyLookup(model["model"], read_edge_dst(model["model"][attr_link])))
+		attr_value = readAssociationDestination(model, attr_link)
 		remove_type(model, attr_link)
-		dict_delete(model["model"], reverseKeyLookup(model["model"], read_edge_dst(model["model"][attr_link])))
+		
+		if (dict_in(model["model"], attr_value)):
+			remove_type(model, attr_value)
+			dict_delete(model["model"], attr_value)
+
 		delete_element(model["model"][attr_link])
 
 	return!
@@ -481,7 +486,7 @@ Void function add_AL_links(model : Element, list : Element, element : Element, t
 	// The name node
 	String link_name
 	link = read_edge_dst(link)
-	link_name = "__" + cast_id2s(link)
+	link_name = "__" + cast_id(link)
 
 	if (bool_not(dict_in(model["model"], link_name))):
 		reuse_element(model, "StringAttr", link_name, link)
@@ -507,12 +512,12 @@ String function add_AL(model : Element, element : Element):
 		elem = list_read(work_node, 0)
 		type = list_read(work_node, 1)
 
-		elem_name = "__" + cast_id2s(elem)
+		elem_name = "__" + cast_id(elem)
 		if (bool_not(set_in(model["model"], elem_name))):
 			// Determine the type if we don't know it
 			if (type == ""):
 				if (is_physical_action(elem)):
-					type = cast_a2s(elem)
+					type = cast_value(elem)
 				else:
 					type = "Element"
 

+ 12 - 10
bootstrap/object_operations.alc

@@ -77,11 +77,12 @@ Element function allOutgoingAssociationInstances(model : Element, source_name :
 	i = 0
 	while (i < all_out):
 		option = reverseKeyLookup(model["model"], read_out(source, i))
-		if (assoc_name != ""):
-			if (is_nominal_instance(model, option, assoc_name)):
+		if (option != ""):
+			if (assoc_name != ""):
+				if (is_nominal_instance(model, option, assoc_name)):
+					set_add(result, option)
+			else:
 				set_add(result, option)
-		else:
-			set_add(result, option)
 		i = i + 1
 
 	return result!
@@ -100,11 +101,12 @@ Element function allIncomingAssociationInstances(model : Element, target_name :
 	i = 0
 	while (i < all_out):
 		option = reverseKeyLookup(model["model"], read_in(source, i))
-		if (assoc_name != ""):
-			if (is_nominal_instance(model, option, assoc_name)):
+		if (option != ""):
+			if (assoc_name != ""):
+				if (is_nominal_instance(model, option, assoc_name)):
+					set_add(result, option)
+			else:
 				set_add(result, option)
-		else:
-			set_add(result, option)
 		i = i + 1
 
 	return result!
@@ -186,9 +188,9 @@ String function print_dict(dict : Element):
 	result = ""
 	while (0 < list_len(keys)):
 		key = set_pop(keys)
-		result = result + cast_v2s(key)
+		result = result + cast_value(key)
 		result = result + ": "
-		result = result + cast_v2s(dict[key])
+		result = result + cast_value(dict[key])
 		result = result + "\n"
 	return result!
 

+ 6 - 16
bootstrap/primitives.alc

@@ -14,22 +14,12 @@ Element function read_edge_src(a: Element) = ?primitives/read_edge_src
 Element function read_edge_dst(a: Element) = ?primitives/read_edge_dst
 Boolean function delete_element(a: Element) = ?primitives/delete_element
 Boolean function element_eq(a: Element, b: Element) = ?primitives/element_eq
-Float function cast_i2f(a: Integer) = ?primitives/cast_i2f
-String function cast_i2s(a: Integer) = ?primitives/cast_i2s
-Boolean function cast_i2b(a: Integer) = ?primitives/cast_i2b
-Integer function cast_f2i(a: Float) = ?primitives/cast_f2i
-Boolean function cast_f2b(a: Float) = ?primitives/cast_f2b
-String function cast_f2s(a: Float) = ?primitives/cast_f2s
-Integer function cast_s2i(a: String) = ?primitives/cast_s2i
-Float function cast_s2f(a: String) = ?primitives/cast_s2f
-Boolean function cast_s2b(a: String) = ?primitives/cast_s2b
-Integer function cast_b2i(a: Boolean) = ?primitives/cast_b2i
-Float function cast_b2f(a: Boolean) = ?primitives/cast_b2f
-String function cast_b2s(a: Boolean) = ?primitives/cast_b2s
-String function cast_e2s(a: Element) = ?primitives/cast_e2s
-String function cast_a2s(a: Action) = ?primitives/cast_a2s
-String function cast_v2s(a: Element) = ?primitives/cast_v2s
-String function cast_id2s(a: Element) = ?primitives/cast_id2s
+Float function cast_float(a: Element) = ?primitives/cast_float
+String function cast_string(a: Element) = ?primitives/cast_string
+Boolean function cast_boolean(a: Element) = ?primitives/cast_boolean
+Integer function cast_integer(a: Element) = ?primitives/cast_integer
+String function cast_value(a: Element) = ?primitives/cast_value
+String function cast_id(a: Element) = ?primitives/cast_id
 Element function dict_add_fast(a: Element, b: Element, c: Element) = ?primitives/dict_add_fast
 Element function dict_delete(a: Element, b: Element) = ?primitives/dict_delete
 Element function dict_delete_node(a: Element, b: Element) = ?primitives/dict_delete_node

+ 22 - 4
bootstrap/ramify.alc

@@ -49,10 +49,12 @@ Element function ramify(model : Element):
 	//  Class LHS : LHS_Root {}
 	instantiate_node(new_model, "Class", "LHS")
 	instantiate_link(new_model, "Inheritance", "", "LHS", "LHS_Root")
+	instantiate_attribute(new_model, "LHS", "name", "LHS")
 
 	//  Class NAC : LHS_Root {}
 	instantiate_node(new_model, "Class", "NAC")
 	instantiate_link(new_model, "Inheritance", "", "NAC", "LHS_Root")
+	instantiate_attribute(new_model, "NAC", "name", "NAC")
 
 	//	Class PreElement {
 	//		label : String
@@ -73,6 +75,7 @@ Element function ramify(model : Element):
 	instantiate_node(new_model, "Class", "RHS")
 	instantiate_attribute(new_model, "RHS", "lower_cardinality", 1)
 	instantiate_attribute(new_model, "RHS", "upper_cardinality", 1)
+	instantiate_attribute(new_model, "RHS", "name", "RHS")
 	model_define_attribute(new_model, "RHS", "action", True, "ActionLanguage")
 
 	//	Class PostElement {
@@ -111,6 +114,7 @@ Element function ramify(model : Element):
 	set_add(copied_attributes, "upper_cardinality")
 	set_add(copied_attributes, "source_upper_cardinality")
 	set_add(copied_attributes, "target_upper_cardinality")
+	set_add(copied_attributes, "name")
 
 	while (list_len(keys) > 0):
 		key = list_pop(keys, 0)
@@ -130,8 +134,12 @@ Element function ramify(model : Element):
 				attr_name = set_pop(local_copied_attributes)
 				if (element_neq(read_attribute(model, key, attr_name), read_root())):
 					// Attribute was defined, so reassign in both LHS and RHS
-					instantiate_attribute(new_model, "Pre_" + key, attr_name, read_attribute(model, key, attr_name))
-					instantiate_attribute(new_model, "Post_" + key, attr_name, read_attribute(model, key, attr_name))
+					if (attr_name == "name"):
+						instantiate_attribute(new_model, "Pre_" + key, attr_name, string_join("Pre_", read_attribute(model, key, attr_name)))
+						instantiate_attribute(new_model, "Post_" + key, attr_name, string_join("Post_", read_attribute(model, key, attr_name)))
+					else:
+						instantiate_attribute(new_model, "Pre_" + key, attr_name, read_attribute(model, key, attr_name))
+						instantiate_attribute(new_model, "Post_" + key, attr_name, read_attribute(model, key, attr_name))
 
 		elif (type_name == "AttributeLink"):
 			// Got an attribute, so find out the source and name
@@ -173,8 +181,12 @@ Element function ramify(model : Element):
 				attr_name = set_pop(local_copied_attributes)
 				if (element_neq(read_attribute(model, key, attr_name), read_root())):
 					// Attribute was defined, so reassign in both LHS and RHS
-					instantiate_attribute(new_model, "Pre_" + key, attr_name, read_attribute(model, key, attr_name))
-					instantiate_attribute(new_model, "Post_" + key, attr_name, read_attribute(model, key, attr_name))
+					if (attr_name == "name"):
+						instantiate_attribute(new_model, "Pre_" + key, attr_name, string_join("Pre_", read_attribute(model, key, attr_name)))
+						instantiate_attribute(new_model, "Post_" + key, attr_name, string_join("Post_", read_attribute(model, key, attr_name)))
+					else:
+						instantiate_attribute(new_model, "Pre_" + key, attr_name, read_attribute(model, key, attr_name))
+						instantiate_attribute(new_model, "Post_" + key, attr_name, read_attribute(model, key, attr_name))
 
 		elif (type_name == "Inheritance"):
 			old_source = reverseKeyLookup(model["model"], read_edge_src(entry))
@@ -196,10 +208,12 @@ Element function ramify(model : Element):
 	//	Class Success : Entry {}
 	instantiate_node(new_model, "Class", "Success")
 	instantiate_link(new_model, "Inheritance", "", "Success", "Entry")
+	instantiate_attribute(new_model, "Success", "name", "Success")
 
 	//	Class Failure : Entry {}
 	instantiate_node(new_model, "Class", "Failure")
 	instantiate_link(new_model, "Inheritance", "", "Failure", "Entry")
+	instantiate_attribute(new_model, "Failure", "name", "Failure")
 
 	//  Class Rule : Entry {}
 	instantiate_node(new_model, "Class", "Rule")
@@ -251,20 +265,24 @@ Element function ramify(model : Element):
 	// 	Class Query : LHSRule {}
 	instantiate_node(new_model, "Class", "Query")
 	instantiate_link(new_model, "Inheritance", "", "Query", "LHSRule")
+	instantiate_attribute(new_model, "Query", "name", "Query")
 
 	//	Class Atomic : LHSRule, RHSRule {}
 	instantiate_node(new_model, "Class", "Atomic")
 	instantiate_link(new_model, "Inheritance", "", "Atomic", "LHSRule")
 	instantiate_link(new_model, "Inheritance", "", "Atomic", "RHSRule")
+	instantiate_attribute(new_model, "Atomic", "name", "Atomic")
 
 	// 	Class ForAll : LHSRule, RHSRule {}
 	instantiate_node(new_model, "Class", "ForAll")
 	instantiate_link(new_model, "Inheritance", "", "ForAll", "LHSRule")
 	instantiate_link(new_model, "Inheritance", "", "ForAll", "RHSRule")
+	instantiate_attribute(new_model, "ForAll", "name", "ForAll")
 
 	//	Class Composite : Rule {}
 	instantiate_node(new_model, "Class", "Composite")
 	instantiate_link(new_model, "Inheritance", "", "Composite", "Rule")
+	instantiate_attribute(new_model, "Composite", "name", "Composite")
 
 	//	Association Initial(Composite, Entry){
 	//		target_lower_cardinality = 1

+ 13 - 2
bootstrap/random.alc

@@ -1,4 +1,5 @@
 include "primitives.alh"
+include "utils.alh"
 
 Integer seed = 1
 
@@ -17,16 +18,26 @@ Float function random():
 	seed = integer_modulo(a * seed + c, m)
 
 	// The seed is the new value
-	return float_division(seed, m)!
+	return float_division(cast_float(seed), cast_float(m))!
 
 Integer function random_interval(a : Integer, b : Integer):
 	if (a == b):
 		return a!
 	else:
-		return cast_f2i(random() * (b - a + 1) + a)!
+		return cast_integer(random() * cast_float(b - a + 1) + cast_float(a))!
 
 Element function random_choice(list : Element):
 	if (list_len(list) == 0):
 		return read_root()!
 	else:
 		return list_read(list, random_interval(0, list_len(list) - 1))!
+
+String function random_string(length : Integer):
+	String result
+	Element chars
+
+	chars = alphabet()
+	result = ""
+	while (string_len(result) < length):
+		result = string_join(result, cast_string(random_choice(chars)))
+	return result!

+ 83 - 12
bootstrap/semi_primitives.alc

@@ -1,4 +1,6 @@
 include "primitives.alh"
+include "utils.alh"
+include "random.alh"
 
 // This function must be kept internally, only called through the "sleep" and "interruptable_sleep" functions
 Float function __sleep(a : Float, b : Boolean) = ?primitives/__sleep
@@ -16,13 +18,12 @@ Boolean function value_neq(a : Element, b : Element):
 	return bool_not(value_eq(a, b))!
 
 Boolean function integer_gt(a : Element, b : Element):
-	return bool_or(integer_lt(a, b), value_eq(a, b))!
+	return bool_not(bool_or(integer_lt(a, b), value_eq(a, b)))!
 
 Boolean function float_gt(a : Element, b : Element):
-	return bool_or(float_lt(a, b), value_eq(a, b))!
+	return bool_not(bool_or(float_lt(a, b), value_eq(a, b)))!
 
 Element function dict_add(a : Element, b : Element, c : Element):
-	log("Doing dict_add for " + cast_v2s(b))
 	create_edge(create_edge(a, c), b)
 	return a!
 
@@ -48,7 +49,7 @@ Element function list_read(a : Element, b : Integer):
 	return dict_read(a, b)!
 
 Element function list_append(a : Element, b : Element):
-	dict_add(a, integer_addition(list_len(a), 1), b)
+	dict_add(a, list_len(a), b)
 	return a!
 
 Element function set_add(a : Element, b : Element):
@@ -70,17 +71,14 @@ Element function set_pop(a : Element):
 		edge = read_out(a, 0)
 		result = read_edge_dst(read_out(edge, 0))
 		delete_element(edge)
-		log("Value: " + cast_v2s(result))
 		return result!
 	else:
-		log("Set pop on empty set!")
 		return read_root()!
 
 Element function set_read(a : Element):
 	if (integer_gt(set_len(a), 0)):
 		return read_edge_dst(read_out(read_out(a, 0), 0))!
 	else:
-		log("Set read on empty set!")
 		return read_root()!
 
 Void function sleep(a : Float):
@@ -168,6 +166,17 @@ String function string_substr(a: String, b: Integer, c: Integer):
 
 		i = i + 1
 	return result!
+
+String function string_replace(a : String, b : String, c : String):
+	Element lst
+	String result
+
+	lst = string_split(a, b)
+	result = cast_string(list_pop_final(lst))
+	while (set_len(lst) > 0):
+		result = cast_string(list_pop_final(lst)) + c + result
+
+	return result!
 	
 Element function resolve(name : String):
 	// Could directly access it through introspection
@@ -201,7 +210,7 @@ String function set_to_string(s : Element):
 	result = "{"
 	s = set_copy(s)
 	while (set_len(s) > 0):
-		result = (result + cast_v2s(set_pop(s))) + ", "
+		result = (result + cast_value(set_pop(s))) + ", "
 	
 	result = result + "}"
 
@@ -214,7 +223,7 @@ String function list_to_string(s : Element):
 	result = "["
 	i = 0
 	while (i < list_len(s)):
-		result = result + cast_v2s(list_read(s, i))
+		result = result + cast_value(list_read(s, i))
 		result = result + ", "
 		i = i + 1
 	
@@ -242,9 +251,9 @@ String function dict_to_string(d : Element):
 	while (set_len(keys) > 0):
 		key = set_pop(keys)
 
-		result = result + cast_v2s(key)
+		result = result + cast_value(key)
 		result = result + ": "
-		result = result + cast_v2s(dict_read_node(d, key))
+		result = result + cast_value(dict_read_node(d, key))
 		if (set_len(keys) > 0):
 			result = result + ", "
 	
@@ -375,7 +384,7 @@ Element function make_reverse_dictionary(dict : Element):
 	keys = dict_keys(dict)
 	while (set_len(keys) > 0):
 		key = set_pop(keys)
-		value = cast_id2s(dict[key])
+		value = cast_id(dict[key])
 		if (dict_in(reverse, value)):
 			dict_delete(reverse, value)
 		dict_add(reverse, value, key)
@@ -486,3 +495,65 @@ Element function range(max : Integer):
 		counter = counter + 1
 
 	return result!
+
+String function spawn(function : Element, arguments : Element):
+	// Define a new task, with all the required stack information
+	// This is taken from the "task_management" code
+	Element task_root
+	Element task_frame
+	Element output_value
+	Element input_value 
+	Element root
+
+	root = read_root()
+	task_root = create_node()
+	task_frame = create_node()
+	output_value = create_node()
+	input_value = create_node()
+
+	dict_add_fast(task_root, "frame", task_frame)
+	dict_add_fast(task_root, "output", output_value)
+	dict_add_fast(task_root, "last_output", output_value)
+	dict_add_fast(task_root, "input", input_value)
+	dict_add_fast(task_root, "last_input", input_value)
+	dict_add_fast(task_frame, "evalstack", create_node())
+	dict_add_fast(task_frame, "returnvalue", create_node())
+	dict_add_fast(task_frame, "phase", "init")
+	dict_add_fast(task_frame, "symbols", create_node())
+
+	// Instead of just spawning, we set a different IP
+	dict_add_fast(task_frame, "IP", function["body"])
+
+	// Additionally, we copy over all globals that we previously had
+	dict_add_fast(task_root, "globals", dict_copy(root[get_taskname()]["globals"]))
+
+	if (dict_in(function, "params")):
+		// And add the arguments to the symbol table
+		Element symbols
+		String arg_names_call
+		Element param_dict
+		Integer arg_i
+		symbols = task_frame["symbols"]
+		arg_names_call = "abcdefghijklmnopqrstuvwxyz"
+		arg_i = 0
+		param_dict = function["params"]
+		
+		arguments = list_copy(arguments)
+		Element t
+		Element entry
+		while (list_len(arguments) > 0):
+			entry = create_node()
+			dict_add(entry, "value", list_pop(arguments, 0))
+			t = create_edge(symbols, entry)
+			create_edge(t, param_dict[string_get(arg_names_call, arg_i)])
+			arg_i = arg_i + 1
+
+	// Add this only at the end, as otherwise the task will already be detected and executed
+	String taskname
+	taskname = random_string(30)
+
+	while (dict_in(read_root(), taskname)):
+		taskname = random_string(30)
+	dict_add_fast(read_root(), taskname, task_root)
+
+	return taskname!

+ 1 - 1
bootstrap/services.alc

@@ -16,7 +16,7 @@ String function comm_newPort():
 	String attempt
 	attempt = "__hierarchy"
 	while (dict_in(root, attempt)):
-		attempt = "__" + get_taskname() + "_" + cast_v2s(services)
+		attempt = "__" + get_taskname() + "_" + cast_value(services)
 		services = services + 1
 
 	// Create queues

+ 0 - 1
bootstrap/tracability.mvc

@@ -1,7 +1,6 @@
 import models/SimpleClassDiagrams as SimpleClassDiagrams
 
 include "primitives.alh"
-include "object_operations.alh"
 
 SimpleClassDiagrams Tracability {
     SimpleAttribute String {

+ 11 - 11
bootstrap/transform.alc

@@ -59,14 +59,14 @@ Element function make_matching_schedule(schedule_model : Element, LHS : String,
 					// If it is an edge, we should also add the target and source
 					if (is_edge(schedule_model["model"][next])):
 						// Add the target/source to the schedule
-						set_add(workset, reverse[cast_id2s(read_edge_src(schedule_model["model"][next]))])
-						set_add(workset, reverse[cast_id2s(read_edge_dst(schedule_model["model"][next]))])
+						set_add(workset, reverse[cast_id(read_edge_src(schedule_model["model"][next]))])
+						set_add(workset, reverse[cast_id(read_edge_dst(schedule_model["model"][next]))])
 
 					// Also add all outgoing links
 					counter = read_nr_out(schedule_model["model"][next])
 					while (counter > 0):
 						counter = counter - 1
-						elem_id = cast_id2s(read_out(schedule_model["model"][next], counter))
+						elem_id = cast_id(read_out(schedule_model["model"][next], counter))
 						if (dict_in(reverse, elem_id)):
 							set_add(workset, reverse[elem_id])
 
@@ -74,7 +74,7 @@ Element function make_matching_schedule(schedule_model : Element, LHS : String,
 					counter = read_nr_in(schedule_model["model"][next])
 					while (counter > 0):
 						counter = counter - 1
-						elem_id = cast_id2s(read_in(schedule_model["model"][next], counter))
+						elem_id = cast_id(read_in(schedule_model["model"][next], counter))
 						if (dict_in(reverse, elem_id)):
 							set_add(workset, reverse[elem_id])
 
@@ -299,7 +299,7 @@ Element function match(host_model : Element, schedule_model : Element, LHS : Str
 	set_add_node(mappings, initial_mapping)
 	while (list_len(schedule) > 0):
 		current_element = list_pop(schedule, list_len(schedule) - 1)
-		//log("Binding element with label " + cast_v2s(read_attribute(schedule_model, current_element, "label")))
+		//log("Binding element with label " + cast_value(read_attribute(schedule_model, current_element, "label")))
 		new_mappings = dict_create()
 
 		while (set_len(mappings) > 0):
@@ -313,7 +313,7 @@ Element function match(host_model : Element, schedule_model : Element, LHS : Str
 				set_add_node(new_mappings, new_map)
 
 		mappings = new_mappings
-		//log("Remaining options: " + cast_v2s(set_len(mappings)))
+		//log("Remaining options: " + cast_value(set_len(mappings)))
 
 		if (set_len(mappings) == 0):
 			// Stop because we have no more options remaining!
@@ -391,8 +391,8 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 		label = list_pop(labels_to_add, list_len(labels_to_add) - 1)
 		if (is_edge(schedule_model["model"][RHS_map[label]])):
 			// Edge
-			src = read_attribute(schedule_model, reverse[cast_id2s(read_edge_src(schedule_model["model"][RHS_map[label]]))], "label")
-			dst = read_attribute(schedule_model, reverse[cast_id2s(read_edge_dst(schedule_model["model"][RHS_map[label]]))], "label")
+			src = read_attribute(schedule_model, reverse[cast_id(read_edge_src(schedule_model["model"][RHS_map[label]]))], "label")
+			dst = read_attribute(schedule_model, reverse[cast_id(read_edge_dst(schedule_model["model"][RHS_map[label]]))], "label")
 
 			// First check whether both source and destination are already created
 			if (bool_and(dict_in(new_mapping, src), dict_in(new_mapping, dst))):
@@ -519,9 +519,9 @@ Boolean function transform_composite(host_model : Element, schedule_model : Elem
 			result_set = allAssociationDestinations(schedule_model, current, "OnFailure")
 
 		if (set_len(result_set) == 0):
-			log("ERROR: no next rule found for execution result " + cast_b2s(result))
+			log("ERROR: no next rule found for execution result " + cast_string(result))
 		elif (set_len(result_set) > 1):
-			log("WARNING: multiple next rules found for execution result " + cast_b2s(result))
+			log("WARNING: multiple next rules found for execution result " + cast_string(result))
 			log("Picking one at random...")
 		current = set_pop(result_set)
 
@@ -563,7 +563,7 @@ Boolean function transform_forall(host_model : Element, schedule_model : Element
 	else:
 		result = False
 
-	//log("Matches in forall: " + cast_v2s(set_len(mappings)))
+	//log("Matches in forall: " + cast_string(set_len(mappings)))
 	while (set_len(mappings) > 0):
 		mapping = set_pop(mappings)
 		RHS = set_pop(allAssociationDestinations(schedule_model, current, "RHSLink"))

+ 9 - 8
bootstrap/typing.alc

@@ -20,10 +20,10 @@ Element function get_type_mapping(model : Element):
 		mm = model["metamodel"]["model"][model["type_mapping"][key]]
 		edge = create_edge(m, mm)
 
-		dict_add_fast(tm_model, cast_id2s(m), m)
-		if (bool_not(dict_in(tm_model, cast_id2s(mm)))):
-			dict_add_fast(tm_model, cast_id2s(mm), mm)
-		dict_add_fast(tm_model, cast_id2s(edge), edge)
+		dict_add_fast(tm_model, cast_id(m), m)
+		if (bool_not(dict_in(tm_model, cast_id(mm)))):
+			dict_add_fast(tm_model, cast_id(mm), mm)
+		dict_add_fast(tm_model, cast_id(edge), edge)
 
 	return tm_model!
 
@@ -43,11 +43,11 @@ Void function set_type_mapping(model : Element, type_mapping_model : Element):
 	while (set_len(keys) > 0):
 		key = set_pop(keys)
 		if (is_edge(type_mapping_model[key])):
-			if (bool_not(bool_or(dict_in(rev_model, cast_id2s(type_mapping_model[key])), dict_in(rev_metamodel, cast_id2s(type_mapping_model[key]))))):
+			if (bool_not(bool_or(dict_in(rev_model, cast_id(type_mapping_model[key])), dict_in(rev_metamodel, cast_id(type_mapping_model[key]))))):
 				// Element is in neither model or metamodel
 				// Must be a typing link!
 				// So add it
-				dict_add_fast(type_mapping, rev_model[cast_id2s(read_edge_src(type_mapping_model[key]))], rev_metamodel[cast_id2s(read_edge_dst(type_mapping_model[key]))])
+				dict_add_fast(type_mapping, rev_model[cast_id(read_edge_src(type_mapping_model[key]))], rev_metamodel[cast_id(read_edge_dst(type_mapping_model[key]))])
 
 	dict_overwrite(model, "type_mapping", type_mapping)
 	return!
@@ -89,10 +89,11 @@ Void function new_type_mapping(model : Element):
 	return !
 
 Void function remove_type(model : Element, name : String):
-	dict_delete(model["type_mapping"], name)
+	if (dict_in(model["type_mapping"], name)):
+		dict_delete(model["type_mapping"], name)
 	
 	String elem
-	elem = cast_id2s(model["model"][name])
+	elem = cast_id(model["model"][name])
 	if (dict_in(model["type_mapping"], elem)):
 		dict_delete(model["type_mapping"], elem)
 

+ 45 - 1
bootstrap/utils.alc

@@ -48,7 +48,7 @@ String function JSON_print(model : Element):
 						else:
 							result = result + ", \"" + attr_key + "\": false"
 					else:
-						result = result + ", \"" + attr_key + "\": " + cast_v2s(attr_value)
+						result = result + ", \"" + attr_key + "\": " + cast_value(attr_value)
 
 			result = result + "}"
 	result = result + "]"
@@ -90,3 +90,47 @@ Void function list_extend(lst : Element, ext : Element):
 
 String function get_taskname():
 	return reverseKeyLookup(read_root(), read_taskroot())!
+
+Element function string_split_nr(str : String, split : String, count : Integer):
+	Element splitted
+	String new
+
+	splitted = string_split(str, split)
+	count = count + 1
+
+	while (list_len(splitted) > count):
+		new = split + cast_string(list_pop_final(splitted))
+		new = cast_string(list_pop_final(splitted)) + new
+		list_append(splitted, new)
+
+	return splitted!
+
+Element function alphabet():
+	Element chars
+	chars = list_create()
+	list_append(chars, "a")
+	list_append(chars, "b")
+	list_append(chars, "c")
+	list_append(chars, "d")
+	list_append(chars, "e")
+	list_append(chars, "f")
+	list_append(chars, "g")
+	list_append(chars, "h")
+	list_append(chars, "i")
+	list_append(chars, "j")
+	list_append(chars, "k")
+	list_append(chars, "l")
+	list_append(chars, "m")
+	list_append(chars, "n")
+	list_append(chars, "o")
+	list_append(chars, "p")
+	list_append(chars, "q")
+	list_append(chars, "s")
+	list_append(chars, "t")
+	list_append(chars, "u")
+	list_append(chars, "v")
+	list_append(chars, "w")
+	list_append(chars, "x")
+	list_append(chars, "y")
+	list_append(chars, "z")
+	return chars!

+ 144 - 0
doc/al_rules/all_rules.tex

@@ -0,0 +1,144 @@
+\documentclass[a4paper]{report}
+\usepackage{graphicx}
+\begin{document}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_access__eval.eps}
+    \caption{access  eval}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_access__init.eps}
+    \caption{access  init}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_assign__assign.eps}
+    \caption{assign  assign}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_assign__init.eps}
+    \caption{assign  init}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_assign__value.eps}
+    \caption{assign  value}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_break.eps}
+    \caption{break}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_call__call-no-params.eps}
+    \caption{call  call-no-params}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_call__call-params.eps}
+    \caption{call  call-params}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_call__params-first-multi.eps}
+    \caption{call  params-first-multi}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_call__params-first-single.eps}
+    \caption{call  params-first-single}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_call__params-last.eps}
+    \caption{call  params-last}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_call__params-next.eps}
+    \caption{call  params-next}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_call__resolve-no-params.eps}
+    \caption{call  resolve-no-params}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_call__resolve-params.eps}
+    \caption{call  resolve-params}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_const.eps}
+    \caption{const}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_continue.eps}
+    \caption{continue}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_declare__init.eps}
+    \caption{declare  init}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_global__init.eps}
+    \caption{global  init}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_if__cond.eps}
+    \caption{if  cond}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_if__false-else.eps}
+    \caption{if  false-else}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_if__false-nothing.eps}
+    \caption{if  false-nothing}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_if__true.eps}
+    \caption{if  true}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_input.eps}
+    \caption{input}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_next__next.eps}
+    \caption{next  next}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_next__no-next.eps}
+    \caption{next  no-next}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_output__init.eps}
+    \caption{output  init}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_output__output.eps}
+    \caption{output  output}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_resolve__no-attr-global.eps}
+    \caption{resolve  no-attr-global}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_resolve__no-attr.eps}
+    \caption{resolve  no-attr}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_return__eval.eps}
+    \caption{return  eval}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_return__no-value.eps}
+    \caption{return  no-value}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_return__value.eps}
+    \caption{return  value}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_while__cond.eps}
+    \caption{while  cond}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_while__false.eps}
+    \caption{while  false}
+\end{figure}
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{rule_while__true.eps}
+    \caption{while  true}
+\end{figure}
+\end{document}

+ 11 - 0
doc/al_rules/auto_gen.py

@@ -0,0 +1,11 @@
+import glob
+
+with open("all_rules.tex", 'w') as f:
+    f.write("\\documentclass[a4paper]{report}\n")
+    f.write("\\usepackage{graphicx}\n")
+    f.write("\\begin{document}\n")
+
+    for inp in sorted(glob.glob("*.eps")):
+        f.write(open("template.tex", 'r').read().replace("FILE", inp).replace("NAME", inp[5:-4].replace("_", " ")))
+
+    f.write("\\end{document}\n")

+ 10 - 0
doc/al_rules/render.sh

@@ -0,0 +1,10 @@
+#!/bin/bash
+for f in *.dot
+do
+    dot -Teps -Gratio=1 -Gsize=30 $f > ${f%%.*}.eps
+done
+
+for f in *.eps
+do
+    epstopdf $f
+done

+ 15 - 0
doc/al_rules/rule_access__eval.dot

@@ -0,0 +1,15 @@
+digraph {
+    node [shape="point"]
+    Inst [shape="oval",label="Access"]
+    Phase [shape="oval",label="'eval'",color="blue"]
+    NewPhase [shape="oval",label="'finish'",color="green"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Inst [label="'IP'"]
+    Frame -> NewReturnValue [label="'returnvalue'",color="green",penwidth=4]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> ReturnValue [label="'returnvalue'",color="blue",style="dashed"]
+    ReturnValue -> NewReturnValue [label="'value'"]
+}

+ 19 - 0
doc/al_rules/rule_access__init.dot

@@ -0,0 +1,19 @@
+digraph {
+    node [shape="point"]
+    Phase [label="'init'",shape="oval"]
+    Inst [label="Access",shape="oval"]
+    NewEvalStack [color="green"]
+    StackPhase [label="'eval'",shape="oval",color="green"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Phase [label="'phase'"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Inst -> Cond [label="'var'"]
+    OldEvalStack -> Inst [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> StackPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Cond [label="'IP'",color="green",penwidth=4]
+}

+ 16 - 0
doc/al_rules/rule_assign__assign.dot

@@ -0,0 +1,16 @@
+digraph {
+    node [shape="point"]
+    Inst [shape="oval",label="Assign"]
+    OldPhase [shape="oval",label="'assign'",color="blue"]
+    NewPhase [shape="oval",label="'finish'",color="green"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Inst [label="'IP'"]
+    Frame -> ReturnValue [label="'returnvalue'"]
+    Frame -> Var [label="'variable'",color="blue",style="dashed"]
+    Var -> ReturnValue [label="'value'",color="green",penwidth=4]
+    Var -> OldValue [label="'value'",color="blue",style="dashed"]
+    Frame -> OldPhase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+}

+ 19 - 0
doc/al_rules/rule_assign__init.dot

@@ -0,0 +1,19 @@
+digraph {
+    node [shape="point"]
+    Phase [label="'init'",shape="oval"]
+    Inst [label="Assign",shape="oval"]
+    NewEvalStack [color="green"]
+    StackPhase [label="'value'",shape="oval",color="green"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Phase [label="'phase'"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Inst -> Cond [label="'var'"]
+    OldEvalStack -> Inst [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> StackPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Cond [label="'IP'",color="green",penwidth=4]
+}

+ 23 - 0
doc/al_rules/rule_assign__value.dot

@@ -0,0 +1,23 @@
+digraph {
+    node [shape="point"]
+    Phase [label="'value'",shape="oval",color="blue"]
+    Inst [label="Assign",shape="oval"]
+    NewEvalStack [color="green"]
+    StackPhase [label="'assign'",shape="oval",color="green"]
+    NewPhase [label="'init'",shape="oval",color="green"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Inst -> Cond [label="'value'"]
+    OldEvalStack -> Inst [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> StackPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Cond [label="'IP'",color="green",penwidth=4]
+    Frame -> Returnvalue [label="'returnvalue'"]
+    Frame -> Returnvalue [label="'variable'",color="green",penwidth=4]
+}

+ 18 - 0
doc/al_rules/rule_break.dot

@@ -0,0 +1,18 @@
+digraph {
+    Root [shape="point"]
+    UserRoot [shape="point"]
+    Frame [shape="point"]
+
+    OldPhase [label="'init'",color="blue"]
+    NewPhase [label="'finish'",color="green"]
+    OldIP [label="Break"]
+    NewIP [label="While"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> OldPhase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> OldIP [label="'IP'",color="blue",style="dashed"]
+    Frame -> NewIP [label="'IP'",color="green",penwidth=4]
+    OldIP -> NewIP [label="'while'"]
+}

+ 30 - 0
doc/al_rules/rule_call__call-no-params.dot

@@ -0,0 +1,30 @@
+digraph {
+    node [shape="point"]
+    Call [label="Call",shape="oval"]
+    Phase [label="'call'",shape="oval",color="blue"]
+    NewPhase [label="'finish'",shape="oval",color="green"]
+    Param [color="red"]
+    NPhase [label="'init'",shape="oval",color="green"]
+    NEvalStack [color="green"]
+    NSymbols [color="green"]
+    NewFrame [color="green"]
+    NewReturnValue [color="green"]
+    
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'",color="blue",style="dashed"]
+    UserRoot -> NewFrame [label="'frame'",color="green",penwidth=4]
+    Frame -> Call [label="'IP'"]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Call -> Param [label="'last_param'",color="red",style="dotted"]
+    Frame -> ReturnValue [label="'returnvalue'"]
+    ReturnValue -> Body [label="'body'"]
+
+    NewFrame -> NEvalStack [label="'evalstack'",color="green",penwidth=4]
+    NewFrame -> NSymbols [label="'symbols'",color="green",penwidth=4]
+    NewFrame -> NPhase [label="'phase'",color="green",penwidth=4]
+    NewFrame -> Frame [label="'prev'",color="green",penwidth=4]
+    NewFrame -> Call [label="'caller'",color="green",penwidth=4]
+    NewFrame -> Body [label="'IP'", color="green",penwidth=4]
+    NewFrame -> NewReturnValue [label="'returnvalue'",color="green",penwidth=4]
+}

+ 34 - 0
doc/al_rules/rule_call__call-params.dot

@@ -0,0 +1,34 @@
+digraph {
+    node [shape="point"]
+    Call [label="Call",shape="oval"]
+    Phase [label="'call'",shape="oval",color="blue"]
+    NewPhase [label="'finish'",color="green",shape="oval"]
+    NVariable [color="green"]
+    mid [color="green",width=0]
+    ParamA_mid [width=0]
+    Name_actual [label="a",shape="oval"]
+    
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'",color="blue",style="dashed"]
+    UserRoot -> NewFrame [label="'frame'",color="green",penwidth=4]
+    Frame -> Call [label="'IP'"]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Call -> ParamN [label="'last_param'"]
+    Frame -> ReturnValue [label="'returnvalue'"]
+
+    ParamN -> Name_actual [label="'name'"]
+
+    NewFrame -> NSymbols [label="'symbols'"]
+    NewFrame -> Frame [label="'prev'"]
+    NewFrame -> Call [label="'caller'"]
+    NewFrame -> Body [label="'IP'"]
+    Signature -> Body [label="'body'"]
+    Signature -> Params [label="'params'"]
+
+    NSymbols -> mid [arrowhead="none",color="green",penwidth=4]
+    mid -> NVariable [color="green",penwidth=4]
+    NVariable -> ReturnValue [color="green",label="'value'",penwidth=4]
+    mid -> ParamA [color="green",penwidth=4]
+    Params -> ParamA [label="a"]
+}

+ 37 - 0
doc/al_rules/rule_call__params-first-multi.dot

@@ -0,0 +1,37 @@
+digraph {
+    node [shape="point"]
+    Call [label="Call",shape="oval"]
+    NewEvalStack [color="green"]
+    NPhase [label="'init'",shape="oval",color="green"]
+    NEvalStack [color="green"]
+    NSymbols [color="green"]
+    NewFrame [color="green"]
+    NewPhase [label="'init'",color="green",shape="oval"]
+    NewReturnValue [color="green"]
+    
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Call [label="'IP'",color="blue",style="dashed"]
+    Frame -> ParamValue [label="'IP'",color="green",penwidth=4]
+    Frame -> Param [label="'phase'",color="blue",style="dashed"]
+    Param -> ParamValue [label="'value'"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Param -> Param2 [label="'next_param'"]
+    OldEvalStack -> Call [label="'inst'",color="green",penwidth=4]
+    Call -> Param [label="'params'"]
+    OldEvalStack -> Param2 [label="'phase'",color="green",penwidth=4]
+    Frame -> ReturnValue [label="'returnvalue'"]
+    ReturnValue -> Body [label="'body'"]
+    ReturnValue -> Params [label="'params'"]
+
+    NewFrame -> NEvalStack [label="'evalstack'",color="green",penwidth=4]
+    NewFrame -> NSymbols [label="'symbols'",color="green",penwidth=4]
+    NewFrame -> NPhase [label="'phase'",color="green",penwidth=4]
+    NewFrame -> Frame [label="'prev'",color="green",penwidth=4]
+    NewFrame -> Call [label="'caller'",color="green",penwidth=4]
+    NewFrame -> Body [label="'IP'", color="green",penwidth=4]
+    NewFrame -> NewReturnValue [label="'returnvalue'",color="green",penwidth=4]
+}

+ 38 - 0
doc/al_rules/rule_call__params-first-single.dot

@@ -0,0 +1,38 @@
+digraph {
+    node [shape="point"]
+    Call [label="Call",shape="oval"]
+    CallString [label="'call'",shape="oval",color="green"]
+    NewEvalStack [color="green"]
+    NPhase [label="'init'",shape="oval",color="green"]
+    NEvalStack [color="green"]
+    NSymbols [color="green"]
+    NewFrame [color="green"]
+    NewPhase [label="'init'",color="green",shape="oval"]
+    NReturnValue [color="green"]
+    
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Call [label="'IP'",color="blue",style="dashed"]
+    Frame -> ParamValue [label="'IP'",color="green",penwidth=4]
+    Param -> ParamValue [label="'value'"]
+    Frame -> Param [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Call -> Param [label="'params'"]
+    Call -> Param [label="'last_param'"]
+    OldEvalStack -> Call [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> CallString [label="'phase'",color="green",penwidth=4]
+    Frame -> ReturnValue [label="'returnvalue'"]
+    ReturnValue -> Body [label="'body'"]
+    ReturnValue -> Params [label="'params'"]
+
+    NewFrame -> NEvalStack [label="'evalstack'",color="green",penwidth=4]
+    NewFrame -> NSymbols [label="'symbols'",color="green",penwidth=4]
+    NewFrame -> NPhase [label="'phase'",color="green",penwidth=4]
+    NewFrame -> Frame [label="'prev'",color="green",penwidth=4]
+    NewFrame -> Call [label="'caller'",color="green",penwidth=4]
+    NewFrame -> Body [label="'IP'", color="green",penwidth=4]
+    NewFrame -> NReturnValue [label="'returnvalue'", color="green",penwidth=4]
+}

+ 40 - 0
doc/al_rules/rule_call__params-last.dot

@@ -0,0 +1,40 @@
+digraph {
+    node [shape="point"]
+    Call [label="Call",shape="oval"]
+    CallString [label="'call'",shape="oval",color="green"]
+    NewEvalStack [color="green"]
+    NewPhase [label="'init'",color="green",shape="oval"]
+    NVariable [color="green"]
+    mid [color="green",width=0]
+    NameA [label="a",shape="oval"]
+    
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Call [label="'IP'",color="blue",style="dashed"]
+    Frame -> Param2Value [label="'IP'",color="green",penwidth=4]
+    Param2 -> Param2Value [label="'value'"]
+    Frame -> Param2 [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Call -> Param2 [label="'last_param'"]
+    Param1 -> Param2 [label="'next_param'"]
+    Param1 -> NameA [label="'name'"]
+    OldEvalStack -> Call [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> CallString [label="'phase'",color="green",penwidth=4]
+    Frame -> ReturnValue [label="'returnvalue'"]
+
+    NewFrame -> NSymbols [label="'symbols'"]
+    NewFrame -> Frame [label="'prev'"]
+    NewFrame -> Call [label="'caller'"]
+    NewFrame -> Body [label="'IP'"]
+    Signature -> Body [label="'body'"]
+    Signature -> Params [label="'params'"]
+
+    NSymbols -> mid [arrowhead="none",color="green",penwidth=4]
+    mid -> NVariable [color="green",penwidth=4]
+    NVariable -> ReturnValue [color="green",label="'value'",penwidth=4]
+    mid -> ParamA [color="green",penwidth=4]
+    Params -> ParamA [label="a"]
+}

+ 39 - 0
doc/al_rules/rule_call__params-next.dot

@@ -0,0 +1,39 @@
+digraph {
+    node [shape="point"]
+    Call [label="Call",shape="oval"]
+    NewEvalStack [color="green"]
+    NewPhase [label="'init'",color="green",shape="oval"]
+    NVariable [color="green"]
+    mid [color="green",width=0]
+    NameA [label="a",shape="oval"]
+    
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Call [label="'IP'",color="blue",style="dashed"]
+    Frame -> Param2Value [label="'IP'",color="green",penwidth=4]
+    Param2 -> Param2Value [label="'value'"]
+    Frame -> Param2 [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Param1 -> Param2 [label="'next_param'"]
+    Param2 -> Param3 [label="'next_param'"]
+    Param1 -> NameA [label="'name'"]
+    OldEvalStack -> Call [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> Param3 [label="'phase'",color="green",penwidth=4]
+    Frame -> ReturnValue [label="'returnvalue'"]
+
+    NewFrame -> NSymbols [label="'symbols'"]
+    NewFrame -> Frame [label="'prev'"]
+    NewFrame -> Call [label="'caller'"]
+    NewFrame -> Body [label="'IP'"]
+    Signature -> Body [label="'body'"]
+    Signature -> Params [label="'params'"]
+
+    NSymbols -> mid [arrowhead="none",color="green",penwidth=4]
+    mid -> NVariable [color="green",penwidth=4]
+    NVariable -> ReturnValue [color="green",label="'value'",penwidth=4]
+    mid -> ParamA [color="green",penwidth=4]
+    Params -> ParamA [label="a"]
+}

+ 21 - 0
doc/al_rules/rule_call__resolve-no-params.dot

@@ -0,0 +1,21 @@
+digraph {
+    node [shape="point"]
+    Call [label="Call",shape="oval"]
+    CallString [label="'call'",shape="oval",color="green"]
+    Phase [label="'init'",shape="oval"]
+    NewEvalStack [color="green"]
+    Param [color="red"]
+    
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Call [label="'IP'",color="blue",style="dashed"]
+    Frame -> Phase [label="'phase'"]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Call -> Func [label="'func'"]
+    Call -> Param [label="'params'",color="red",style="dotted"]
+    Frame -> Func [label="'IP'",color="green",penwidth=4]
+    OldEvalStack -> Call [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> CallString [label="'phase'",color="green",penwidth=4]
+}

+ 19 - 0
doc/al_rules/rule_call__resolve-params.dot

@@ -0,0 +1,19 @@
+digraph {
+    node [shape="point"]
+    Call [label="Call",shape="oval"]
+    Phase [label="'init'",shape="oval"]
+    NewEvalStack [color="green"]
+    
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Call [label="'IP'",color="blue",style="dashed"]
+    Frame -> Phase [label="'phase'"]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Call -> Func [label="'func'"]
+    Call -> Param [label="'params'"]
+    Frame -> Func [label="'IP'",color="green",penwidth=4]
+    OldEvalStack -> Call [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> Param [label="'phase'",color="green",penwidth=4]
+}

+ 20 - 0
doc/al_rules/rule_const.dot

@@ -0,0 +1,20 @@
+digraph {
+    Root [shape="point"]
+    UserRoot [shape="point"]
+    Frame [shape="point"]
+    n [shape="point"]
+    OldReturnValue [shape="point"]
+
+    OldPhase [label="'init'",color="blue"]
+    NewPhase [label="'finish'",color="green"]
+    OldIP [label="Const"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> OldPhase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> OldIP [label="'IP'"]
+    OldIP -> n [label="'node'"]
+    Frame -> n [label="'returnvalue'",color="green",penwidth=4]
+    Frame -> OldReturnValue [label="'returnvalue'",color="blue",style="dashed"]
+}

+ 16 - 0
doc/al_rules/rule_continue.dot

@@ -0,0 +1,16 @@
+digraph {
+    Root [shape="point"]
+    UserRoot [shape="point"]
+    Frame [shape="point"]
+
+    OldPhase [label="'init'"]
+    OldIP [label="Break"]
+    NewIP [label="While"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> OldPhase [label="'phase'"]
+    Frame -> OldIP [label="'IP'",color="blue",style="dashed"]
+    Frame -> NewIP [label="'IP'",color="green",penwidth=4]
+    OldIP -> NewIP [label="'while'"]
+}

+ 25 - 0
doc/al_rules/rule_declare__init.dot

@@ -0,0 +1,25 @@
+digraph {
+    Root [shape="point"]
+    UserRoot [shape="point"]
+    Frame [shape="point"]
+
+    OldPhase [label="'init'",color="blue"]
+    NewPhase [label="'finish'",color="green"]
+    IP [label="Declare"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> OldPhase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> IP [label="'IP'"]
+    IP -> Formal [label="'var'"]
+
+    Symbols [shape="point"]
+    Empty [shape="point",color="green"]
+    Formal [shape="point"]
+    Frame -> Symbols [label="'symbols'"]
+    Symbols -> mid [arrowhead="none", color="green",penwidth=4]
+    mid [shape="point",color="green"]
+    mid -> Empty [color="green",penwidth=4]
+    mid -> Formal [color="green",penwidth=4]
+}

+ 25 - 0
doc/al_rules/rule_global__init.dot

@@ -0,0 +1,25 @@
+digraph {
+    Root [shape="point"]
+    UserRoot [shape="point"]
+    Frame [shape="point"]
+
+    OldPhase [label="'init'",color="blue"]
+    NewPhase [label="'finish'",color="green"]
+    IP [label="Global"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> GlobalSymbols [label="globals"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> OldPhase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> IP [label="'IP'"]
+    IP -> Formal [label="'var'"]
+
+    GlobalSymbols [shape="point"]
+    Empty [shape="point",color="green"]
+    Formal [shape="point"]
+    GlobalSymbols -> mid [arrowhead="none", color="green",penwidth=4]
+    mid [shape="point",color="green"]
+    mid -> Empty [color="green",penwidth=4]
+    mid -> Formal [color="green",penwidth=4]
+}

+ 19 - 0
doc/al_rules/rule_if__cond.dot

@@ -0,0 +1,19 @@
+digraph {
+    node [shape="point"]
+    Phase [label="'init'",shape="oval"]
+    Inst [label="If",shape="oval"]
+    NewEvalStack [color="green"]
+    StackPhase [label="'cond'",shape="oval",color="green"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Phase [label="'phase'"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Inst -> Cond [label="'cond'"]
+    OldEvalStack -> Inst [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> StackPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Cond [label="'IP'",color="green",penwidth=4]
+}

+ 23 - 0
doc/al_rules/rule_if__false-else.dot

@@ -0,0 +1,23 @@
+digraph {
+    node [shape="point"]
+    Phase [label="'cond'",shape="oval"]
+    Inst [label="If",shape="oval"]
+    NewEvalStack [color="green"]
+    StackPhase [label="'finish'",shape="oval",color="green"]
+    ReturnValue [label="False",shape="oval"]
+    NewPhase [label="'init'",shape="oval",color="green"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Inst -> Block [label="'else'"]
+    OldEvalStack -> Inst [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> StackPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Block [label="'IP'",color="green",penwidth=4]
+    Frame -> ReturnValue [label="'returnvalue'"]
+}

+ 16 - 0
doc/al_rules/rule_if__false-nothing.dot

@@ -0,0 +1,16 @@
+digraph {
+    node [shape="point"]
+    Phase [label="'cond'",shape="oval",color="blue"]
+    NewPhase [label="'finish'",shape="oval",color="green"]
+    Inst [label="If",shape="oval"]
+    ReturnValue [label="False",shape="oval"]
+    Block [color="red"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Inst [label="'IP'"]
+    Inst -> Block [label="'else'",color="red",style="dotted"]
+    Frame -> ReturnValue [label="'returnvalue'"]
+}

+ 23 - 0
doc/al_rules/rule_if__true.dot

@@ -0,0 +1,23 @@
+digraph {
+    node [shape="point"]
+    Phase [label="'cond'",shape="oval",color="blue"]
+    Inst [label="If",shape="oval"]
+    NewEvalStack [color="green"]
+    StackPhase [label="'finish'",shape="oval",color="green"]
+    NewPhase [label="'init'",shape="oval",color="green"]
+    ReturnValue [label="True",shape="oval"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Inst -> Block [label="'then'"]
+    OldEvalStack -> Inst [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> StackPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Block [label="'IP'",color="green",penwidth=4]
+    Frame -> ReturnValue [label="'returnvalue'"]
+}

+ 25 - 0
doc/al_rules/rule_input.dot

@@ -0,0 +1,25 @@
+digraph {
+    Root [shape="point"]
+    UserRoot [shape="point"]
+    Frame [shape="point"]
+    InputNext [shape="point"]
+    IP [label="Input"]
+    Value [shape="point"]
+
+    OldPhase [label="'init'",color="blue"]
+    NewPhase [label="'finish'",color="green"]
+    OldReturnvalue [shape="point",color="blue"]
+    Input [shape="point",color="blue"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    UserRoot -> Input [label="'input'",color="blue",style="dashed"]
+    Input -> InputNext [label="'next'",color="blue",style="dashed"]
+    UserRoot -> InputNext [label="'input'",color="green",penwidth=4]
+    Input -> Value [label="'value'",color="blue",style="dashed"]
+    Frame -> OldPhase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> OldReturnvalue [label="'returnvalue'",color="blue",style="dashed"]
+    Frame -> Value [label="'returnvalue'",color="green",penwidth=4]
+    Frame -> IP [label="'IP'"]
+}

+ 13 - 0
doc/al_rules/rule_next__next.dot

@@ -0,0 +1,13 @@
+digraph {
+    node [shape="point"]
+    Phase [label="'finish'",color="blue",shape="oval"]
+    NewPhase [label="'init'",color="green",shape="oval"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Inst -> NextInst [label="'next'"]
+    Frame -> NextInst [label="'IP'",color="green",penwidth=4]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+}

+ 19 - 0
doc/al_rules/rule_next__no-next.dot

@@ -0,0 +1,19 @@
+digraph {
+    node [shape="point"]
+    Phase [color="blue",label="'finish'",shape="oval"]
+    NoInst [color="red"]
+    NewEvalStack [color="blue"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Inst -> NoInst [label="'next'",color="red",style="dotted"]
+    Frame -> NextInst [label="'IP'",color="green",penwidth=4]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NextPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="green",penwidth=4]
+    Frame -> NewEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="blue",style="dashed"]
+    OldEvalStack -> NextInst [label="'inst'",color="blue",style="dashed"]
+    OldEvalStack -> NextPhase [label="'phase'",color="blue",style="dashed"]
+}

+ 19 - 0
doc/al_rules/rule_output__init.dot

@@ -0,0 +1,19 @@
+digraph {
+    node [shape="point"]
+    Phase [label="'init'",shape="oval"]
+    Inst [label="Output",shape="oval"]
+    NewEvalStack [color="green"]
+    StackPhase [label="'output'",shape="oval",color="green"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Phase [label="'phase'"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Inst -> Cond [label="'value'"]
+    OldEvalStack -> Inst [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> StackPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Cond [label="'IP'",color="green",penwidth=4]
+}

+ 23 - 0
doc/al_rules/rule_output__output.dot

@@ -0,0 +1,23 @@
+digraph {
+    Root [shape="point"]
+    UserRoot [shape="point"]
+    Frame [shape="point"]
+    IP [label="Output"]
+
+    OldPhase [label="'output'",color="blue"]
+    NewPhase [label="'finish'",color="green"]
+    Returnvalue [shape="point"]
+    Output [shape="point"]
+    OutputNext [shape="point",color="green"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    UserRoot -> Output [label="'last_output'",color="blue",style="dashed"]
+    Output -> OutputNext [label="'next'",color="green",penwidth=4]
+    UserRoot -> OutputNext [label="'last_output'",color="green",penwidth=4]
+    Output -> Returnvalue [label="'value'",color="green",penwidth=4]
+    Frame -> OldPhase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Returnvalue [label="'returnvalue'"]
+    Frame -> IP [label="'IP'"]
+}

+ 27 - 0
doc/al_rules/rule_resolve__no-attr-global.dot

@@ -0,0 +1,27 @@
+digraph {
+    node [shape="point"]
+    Inst [shape="oval",label="Resolve"]
+    Phase [shape="oval",label="'init'",color="blue"]
+    NewPhase [shape="oval",label="'finish'",color="green"]
+    mid [width=0]
+    mid2 [width=0]
+    NonExisting [color="red"]
+
+    Root -> UserRoot [label="username"]
+    Root -> Global [label="'__global'"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Inst [label="'IP'"]
+    Frame -> NewReturnValue [label="'returnvalue'",color="green",penwidth=4]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Symbols -> mid [arrowhead="none",color="red",style="dotted"]
+    mid -> NonExisting [color="red",style="dotted"]
+    mid -> Var [color="red",style="dotted",constraint="none"]
+    Frame -> ReturnValue [label="'returnvalue'",color="blue",style="dashed"]
+    Frame -> Symbols [label="'symbols'"]
+    Inst -> Var [label="'var'"]
+
+    Global -> mid2 [arrowhead="none"]
+    mid2 -> NewReturnValue
+    mid2 -> Var [constraint="none"]
+}

+ 20 - 0
doc/al_rules/rule_resolve__no-attr.dot

@@ -0,0 +1,20 @@
+digraph {
+    node [shape="point"]
+    Inst [shape="oval",label="Resolve"]
+    Phase [shape="oval",label="'init'",color="blue"]
+    NewPhase [shape="oval",label="'finish'",color="green"]
+    mid [width=0]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Inst [label="'IP'"]
+    Frame -> NewReturnValue [label="'returnvalue'",color="green",penwidth=4]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Symbols -> mid [arrowhead="none"]
+    mid -> NewReturnValue
+    mid -> Var
+    Frame -> ReturnValue [label="'returnvalue'",color="blue",style="dashed"]
+    Frame -> Symbols [label="'symbols'"]
+    Inst -> Var [label="'var'"]
+}

+ 16 - 0
doc/al_rules/rule_return__eval.dot

@@ -0,0 +1,16 @@
+digraph {
+    node [shape="point"]
+    Frame [color="blue"]
+    Phase [label="'eval'",shape="oval",color="blue"]
+    Inst [label="Return",shape="oval"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'",color="blue",style="dashed"]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> PrevFrame [label="'prev'",color="blue",style="dashed"]
+    Frame -> ReturnValue [label="'returnvalue'",color="blue",style="dashed"]
+    PrevFrame -> ReturnValue [label="'returnvalue'",color="green",penwidth=4]
+    UserRoot -> PrevFrame [label="'frame'",color="green",penwidth=4]
+    PrevFrame -> OldReturnValue [label="'returnvalue'",color="blue",style="dashed"]
+}

+ 15 - 0
doc/al_rules/rule_return__no-value.dot

@@ -0,0 +1,15 @@
+digraph {
+    node [shape="point"]
+    Frame [color="blue"]
+    Phase [label="'init'",shape="oval",color="blue"]
+    Inst [label="Return",shape="oval"]
+    Value [color="red"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'",color="blue",style="dashed"]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> PrevFrame [label="'prev'",color="blue",style="dashed"]
+    UserRoot -> PrevFrame [label="'frame'",color="green",penwidth=4]
+    Inst -> Value [label="'value'",color="red",style="dotted"]
+}

+ 19 - 0
doc/al_rules/rule_return__value.dot

@@ -0,0 +1,19 @@
+digraph {
+    node [shape="point"]
+    Phase [label="'init'",shape="oval"]
+    Inst [label="Return",shape="oval"]
+    NewEvalStack [color="green"]
+    StackPhase [label="'eval'",shape="oval",color="green"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Phase [label="'phase'"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Inst -> Cond [label="'value'"]
+    OldEvalStack -> Inst [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> StackPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Cond [label="'IP'",color="green",penwidth=4]
+}

+ 19 - 0
doc/al_rules/rule_while__cond.dot

@@ -0,0 +1,19 @@
+digraph {
+    node [shape="point"]
+    Phase [label="'init'",shape="oval"]
+    Inst [label="While",shape="oval"]
+    NewEvalStack [color="green"]
+    StackPhase [label="'cond'",shape="oval",color="green"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Phase [label="'phase'"]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Inst -> Cond [label="'cond'"]
+    OldEvalStack -> Inst [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> StackPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Cond [label="'IP'",color="green",penwidth=4]
+}

+ 14 - 0
doc/al_rules/rule_while__false.dot

@@ -0,0 +1,14 @@
+digraph {
+    node [shape="point"]
+    Phase [label="'cond'",shape="oval",color="blue"]
+    NewPhase [label="'finish'",shape="oval",color="green"]
+    Inst [label="While",shape="oval"]
+    ReturnValue [label="False",shape="oval"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Inst [label="'IP'"]
+    Frame -> ReturnValue [label="'returnvalue'"]
+}

+ 23 - 0
doc/al_rules/rule_while__true.dot

@@ -0,0 +1,23 @@
+digraph {
+    node [shape="point"]
+    Phase [label="'cond'",shape="oval",color="blue"]
+    NewPhase [label="'init'",shape="oval",color="green"]
+    Inst [label="While",shape="oval"]
+    NewEvalStack [color="green"]
+    StackPhase [label="'init'",shape="oval",color="green"]
+    ReturnValue [label="True",shape="oval"]
+
+    Root -> UserRoot [label="username"]
+    UserRoot -> Frame [label="'frame'"]
+    Frame -> Phase [label="'phase'",color="blue",style="dashed"]
+    Frame -> NewPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> NewEvalStack [label="'evalstack'",color="green",penwidth=4]
+    Frame -> OldEvalStack [label="'evalstack'",color="blue",style="dashed"]
+    NewEvalStack -> OldEvalStack [label="'prev'",color="green",penwidth=4]
+    Frame -> Inst [label="'IP'",color="blue",style="dashed"]
+    Inst -> Block [label="'body'"]
+    OldEvalStack -> Inst [label="'inst'",color="green",penwidth=4]
+    OldEvalStack -> StackPhase [label="'phase'",color="green",penwidth=4]
+    Frame -> Block [label="'IP'",color="green",penwidth=4]
+    Frame -> ReturnValue [label="'returnvalue'"]
+}

+ 4 - 0
doc/al_rules/template.tex

@@ -0,0 +1,4 @@
+\begin{figure}[h!]
+    \includegraphics[width=\textwidth]{FILE}
+    \caption{NAME}
+\end{figure}

+ 2 - 0
hybrid_server/classes/mvkcontroller.xml

@@ -27,6 +27,8 @@
             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':

+ 1 - 0
hybrid_server/server.xml

@@ -18,6 +18,7 @@
         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

+ 2 - 2
integration/code/pm_pn_reachability.mvc

@@ -14,11 +14,11 @@ Exec reachability_print{
 }
 
 Data pn {
-    name = "test/pn"
+    name = "pn"
     type = "test/PetriNet"
 }
 Data reachability_graph {
-    name = "test/reachability"
+    name = "reachability"
     type = "test/ReachabilityGraph"
 }
 

+ 1 - 1
integration/code/pn_print.mvc

@@ -14,7 +14,7 @@ Composite schedule {
                 label = "0"
                 action = $
                     Void function action(model : Element, name : String, mapping : Element):
-                        output((cast_v2s(read_attribute(model, name, "name")) + " --> ") + cast_v2s(read_attribute(model, name, "tokens")))
+                        output((cast_value(read_attribute(model, name, "name")) + " --> ") + cast_value(read_attribute(model, name, "tokens")))
                         return!
                     $
             }

+ 6 - 6
integration/code/reachability.alc

@@ -77,8 +77,8 @@ Boolean function reachability_graph(model : Element):
 	set_add(workset, state_id)
 
 	// And add in the model itself
-	state = instantiate_node(model, "ReachabilityGraph/InitialState", cast_i2s(state_id))
-	instantiate_attribute(model, state, "name", cast_i2s(state_id))
+	state = instantiate_node(model, "ReachabilityGraph/InitialState", cast_string(state_id))
+	instantiate_attribute(model, state, "name", cast_string(state_id))
 	instantiate_attribute(model, state, "error", False)
 	keys = dict_keys(dict_repr)
 	while (read_nr_out(keys) > 0):
@@ -148,8 +148,8 @@ Boolean function reachability_graph(model : Element):
 					set_add(workset, target_id)
 
 					// And add in the model itself
-					state = instantiate_node(model, "ReachabilityGraph/State", cast_i2s(target_id))
-					instantiate_attribute(model, state, "name", cast_i2s(target_id))
+					state = instantiate_node(model, "ReachabilityGraph/State", cast_string(target_id))
+					instantiate_attribute(model, state, "name", cast_string(target_id))
 					instantiate_attribute(model, state, "error", False)
 
 					keys = dict_keys(new_dict_repr)
@@ -174,8 +174,8 @@ Boolean function reachability_graph(model : Element):
 				dict_add_fast(mappings[state_id], transition, target_id)
 
 				// And also store it in the model itself
-				new_transition = instantiate_link(model, "ReachabilityGraph/Transition", "", cast_i2s(state_id), cast_i2s(target_id))
+				new_transition = instantiate_link(model, "ReachabilityGraph/Transition", "", cast_string(state_id), cast_string(target_id))
 				instantiate_attribute(model, new_transition, "name", read_attribute(model, transition, "name"))
 
-	log("# reachable states: " + cast_v2s(next_id))
+	log("# reachable states: " + cast_value(next_id))
 	return True!

+ 4 - 4
integration/code/reachability_subfunction.alc

@@ -77,7 +77,7 @@ Boolean function main(model : Element):
 	set_add(workset, state_id)
 
 	// And add in the model itself
-	state = create_state(model, cast_i2s(state_id), dict_repr, cache, True)
+	state = create_state(model, cast_string(state_id), dict_repr, cache, True)
 
 	while (read_nr_out(workset) > 0):
 		state_id = set_pop(workset)
@@ -139,16 +139,16 @@ Boolean function main(model : Element):
 					set_add(workset, target_id)
 
 					// And add in the model itself
-					create_state(model, cast_i2s(target_id), new_dict_repr, cache, False)
+					create_state(model, cast_string(target_id), new_dict_repr, cache, False)
 
 				// Anyway, we have found a transition, which we should store
 				dict_add_fast(mappings[state_id], transition, target_id)
 
 				// And also store it in the model itself
-				new_transition = instantiate_link(model, "ReachabilityGraph/Transition", "", cast_i2s(state_id), cast_i2s(target_id))
+				new_transition = instantiate_link(model, "ReachabilityGraph/Transition", "", cast_string(state_id), cast_string(target_id))
 				instantiate_attribute(model, new_transition, "name", read_attribute(model, transition, "name"))
 
-	log("# reachable states: " + cast_v2s(next_id))
+	log("# reachable states: " + cast_string(next_id))
 	return True!
 
 String function create_state(model : Element, name : String, dict_repr : Element, cache : Element, initial : Boolean):

+ 4 - 4
integration/code/reachabilitygraph_print.mvc

@@ -24,8 +24,8 @@ Composite schedule {
                         while (set_len(all_values) > 0):
                             place = set_pop(all_values)
                             dict_add(dict_values, read_attribute(model, place, "name"), read_attribute(model, place, "tokens"))
-                        log((cast_v2s(read_attribute(model, name, "name")) + ": ") + dict_to_string(dict_values))
-                        output((cast_v2s(read_attribute(model, name, "name")) + ": ") + dict_to_string(dict_values))
+                        log((cast_value(read_attribute(model, name, "name")) + ": ") + dict_to_string(dict_values))
+                        output((cast_value(read_attribute(model, name, "name")) + ": ") + dict_to_string(dict_values))
                         return!
                     $
             }
@@ -55,8 +55,8 @@ Composite schedule {
                 label = "2"
                 action = $
                     Void function action(model : Element, name : String, mapping : Element):
-                        log((((cast_v2s(read_attribute(model, mapping["0"], "name")) + " --[") + cast_v2s(read_attribute(model, name, "name"))) + "]--> ") + cast_v2s(read_attribute(model, mapping["1"], "name")))
-                        output((((cast_v2s(read_attribute(model, mapping["0"], "name")) + " --[") + cast_v2s(read_attribute(model, name, "name"))) + "]--> ") + cast_v2s(read_attribute(model, mapping["1"], "name")))
+                        log((((cast_value(read_attribute(model, mapping["0"], "name")) + " --[") + cast_value(read_attribute(model, name, "name"))) + "]--> ") + cast_value(read_attribute(model, mapping["1"], "name")))
+                        output((((cast_value(read_attribute(model, mapping["0"], "name")) + " --[") + cast_value(read_attribute(model, name, "name"))) + "]--> ") + cast_value(read_attribute(model, mapping["1"], "name")))
                         return!
                     $
             }

+ 64 - 41
integration/test_powerwindow.py

@@ -2,6 +2,8 @@ import unittest
 
 from utils import *
 import sys
+import os
+import shutil
 
 sys.path.append("wrappers")
 from modelverse import *
@@ -36,20 +38,20 @@ class TestPowerWindow(unittest.TestCase):
         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(context):
-            instantiate(None, "Association", ("PW_Control/State", "Encapsulated_PetriNet/Place"), ID="CTRL2EPN_link", context=context)
-            instantiate(None, "Association", ("PW_Control/Transition", "Encapsulated_PetriNet/Transition"), ID="CTRL2EPN_tlink", context=context)
+        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(context):
-            instantiate(None, "Association", ("PW_Plant/State", "Encapsulated_PetriNet/Place"), ID="PLANT2EPN_link", context=context)
-            instantiate(None, "Association", ("PW_Plant/Transition", "Encapsulated_PetriNet/Transition"), ID="PLANT2EPN_tlink", context=context)
+        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(context):
-            instantiate(None, "Association", ("PW_Environment/Event", "Encapsulated_PetriNet/Place"), ID="ENV2EPN_link", context=context)
+        def tracability_ENV2EPN(model):
+            instantiate(model, "Association", ("PW_Environment/Event", "Encapsulated_PetriNet/Place"), ID="ENV2EPN_link")
 
-        def tracability_EPN2PN(context):
-            instantiate(None, "Association", ("Encapsulated_PetriNet/Place", "PetriNet/Place"), ID="EPN2PN_transition_link", context=context)
-            instantiate(None, "Association", ("Encapsulated_PetriNet/Transition", "PetriNet/Transition"), ID="EPN2PN_place_link", context=context)
+        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)
@@ -62,18 +64,26 @@ class TestPowerWindow(unittest.TestCase):
         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())
 
-        global called
-        called = 0
         nr_of_operations = 6
 
+        try:
+            shutil.rmtree(".TEST_POWER_WINDOW")
+        except:
+            pass
+        os.makedirs(".TEST_POWER_WINDOW")
+
         def get_function(filename):
-            def func(context):
-                global called
+            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:
-                    called += 1
-                model_overwrite(None, open(filename, "r").read(), context=context)
+                    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")
@@ -93,11 +103,13 @@ class TestPowerWindow(unittest.TestCase):
             }
 
         try:
-            process_execute("models/pm_powerwindow", "pm_", callbacks)
+            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))
@@ -124,20 +136,20 @@ class TestPowerWindow(unittest.TestCase):
         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(context):
-            instantiate(None, "Association", ("PW_Control/State", "Encapsulated_PetriNet/Place"), ID="CTRL2EPN_link", context=context)
-            instantiate(None, "Association", ("PW_Control/Transition", "Encapsulated_PetriNet/Transition"), ID="CTRL2EPN_tlink", context=context)
+        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(context):
-            instantiate(None, "Association", ("PW_Plant/State", "Encapsulated_PetriNet/Place"), ID="PLANT2EPN_link", context=context)
-            instantiate(None, "Association", ("PW_Plant/Transition", "Encapsulated_PetriNet/Transition"), ID="PLANT2EPN_tlink", context=context)
+        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(context):
-            instantiate(None, "Association", ("PW_Environment/Event", "Encapsulated_PetriNet/Place"), ID="ENV2EPN_link", context=context)
+        def tracability_ENV2EPN(model):
+            instantiate(model, "Association", ("PW_Environment/Event", "Encapsulated_PetriNet/Place"), ID="ENV2EPN_link")
 
-        def tracability_EPN2PN(context):
-            instantiate(None, "Association", ("Encapsulated_PetriNet/Place", "PetriNet/Place"), ID="EPN2PN_transition_link", context=context)
-            instantiate(None, "Association", ("Encapsulated_PetriNet/Transition", "PetriNet/Transition"), ID="EPN2PN_place_link", context=context)
+        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)
@@ -153,27 +165,35 @@ class TestPowerWindow(unittest.TestCase):
         #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())
 
-        global called
-        called = 0
+        try:
+            shutil.rmtree(".TEST_POWER_WINDOW")
+        except:
+            pass
+        os.makedirs(".TEST_POWER_WINDOW")
+
         executed = set([])
 
         def get_function(filename, fixed=None):
-            def func(context):
-                global called
-                if called > len(callbacks) * 2:
+            def func(model):
+                import uuid
+                import os
+                import glob
+                nr_operations = 11
+                called = len(os.listdir(".TEST_POWER_WINDOW/"))
+                if (len(os.listdir(".TEST_POWER_WINDOW")) > nr_operations):
                     raise Exception("Seemingly called some operation twice!")
-                called += 1
-                if filename not in executed or fixed is None:
-                    executed.add(filename)
-                    model_overwrite(None, open(filename, "r").read(), context=context)
+                elif (len(glob.glob(".TEST_POWER_WINDOW/%s_*" % str(filename.rsplit("/", 1)[-1]))) == 0) or fixed is None:
+                    model_overwrite(model, open(filename, "r").read())
                 else:
-                    model_overwrite(None, open(fixed, "r").read(), context=context)
+                    model_overwrite(model, open(fixed, "r").read())
+
+                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", "models/control_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")
 
@@ -194,10 +214,13 @@ class TestPowerWindow(unittest.TestCase):
                 "models/bfs": (ctrl, "inp", "outp"),
             }
 
-        process_execute("models/pm_powerwindow", "pm_", callbacks)
+        process_execute("models/pm_powerwindow", {}, callbacks)
 
         thrd.join()
 
+        called = len(os.listdir(".TEST_POWER_WINDOW"))
+        shutil.rmtree(".TEST_POWER_WINDOW")
+
         if called != 11:
             print(called)
             raise Exception("Not executed sufficiently:" + str(called))

+ 3 - 2
interface/HUTN/hutn_compiler/semantics_visitor.py

@@ -242,9 +242,8 @@ class SemanticsVisitor(Visitor):
 
     @staticmethod
     def cast_name(from_type, to_type):
-        from_t = str(from_type)[0].lower()
         to_t = str(to_type)[0].lower()
-        cast_name = "cast_{}2{}".format(from_t, to_t)
+        cast_name = "cast_" + {"f": "float", "i": "integer", "b": "boolean", "s": "string"}[to_t]
         return cast_name
 
     def raise_implicit_cast_error(self, from_type, to_type, tree):
@@ -564,6 +563,7 @@ class SemanticsVisitor(Visitor):
                                        tree.startpos['column'],
                                        symbol.signature()))
 
+        """
         for i in range(len(expressions)):
             arg_type = self.get_type(expressions[i])
             param_type = symbol.params[i]
@@ -581,6 +581,7 @@ class SemanticsVisitor(Visitor):
             if type(arg_type) != type(param_type):
                 self.perform_implicit_cast(tree, expressions[i], arg_type,
                                            param_type)
+        """
 
         if symbol.name == "__input":
             tree.head = "input"

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

@@ -0,0 +1 @@
+Boolean function write_file(filename : String, content : String)

+ 3 - 0
interface/HUTN/includes/io.alh

@@ -1,3 +1,6 @@
 Element function input()
 Void function output(value : Element)
 Element function input_timeout(timeout : Float)
+Boolean function other_has_output(comm : String)
+Void function give_input_to_other(comm : String, value : Element)
+Element function get_output_from_other(comm : String)

+ 1 - 1
interface/HUTN/includes/mini_modify.alh

@@ -1,4 +1,4 @@
-Element function modify(model : Element, write : Boolean)
+Boolean function modify(model : Element, write : Boolean)
 String function pretty_print(model : Element)
 String function single_input(prompt : String)
 Element function set_input(prompt : String)

+ 8 - 16
interface/HUTN/includes/primitives.alh

@@ -16,22 +16,12 @@ 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) 
+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)
@@ -83,6 +73,7 @@ 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 string_replace(a : String, b : String, c : String)
 String function log(a: String)
 Element function read_root()
 Element function read_taskroot()
@@ -129,3 +120,4 @@ Element function reverseKeyLookupMulti(a: Element, b: Element)
 Element function dict_values(dict : Element)
 Boolean function is_error(a : Element)
 Element function range(max : Integer)
+String function spawn(function : Element, arguments : Element)

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

@@ -1,3 +1,4 @@
 Float function random()
 Integer function random_interval(a : Integer, b : Integer)
 Element function random_choice(list : Element)
+String function random_string(length : Integer)

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

@@ -4,3 +4,5 @@ Element function list_splice(lst : Element, start : Integer, end : Integer)
 Void function list_extend(lst : Element, ext : Element)
 String function get_taskname()
 Void function sleep(seconds : Float)
+Element function alphabet()
+Element function string_split_nr(str : String, split : String, count : Integer)

+ 3 - 2
interface/plot/main.py

@@ -6,14 +6,15 @@ sys.path.append("wrappers/")
 from MatPlotLibWrapper import *
 from plot import *
 from modelverse import *
+import uuid
 
 # Login to Modelverse and have model rendered
 init()
 login("admin", "admin")
-rendered = model_render(sys.argv[1], sys.argv[2])
+rendered = model_render(sys.argv[1], "models/trace_mapper", "rendered/%s" % str(uuid.uuid4()))
 
 # Convert rendered to "MatPlotLib JSON"
-data = json.loads(rendered)
+data = rendered
 plots = {}
 axis = {}
 datasets = {}

+ 67 - 0
interface/simple_plot/main.py

@@ -0,0 +1,67 @@
+import sys
+import matplotlib.pyplot as plt
+import json
+import threading
+
+def read_data():
+    try:
+        return json.load(open("/tmp/values.pickle", 'r'))
+    except:
+        return (0.0, {})
+
+def write_data(values):
+    json.dump(values, open("/tmp/values.pickle", 'w'))
+
+plt.ion()
+plt.figure()
+
+old_time, d = read_data()
+plt.pause(0.01)
+l = sys.stdin.readline()
+time, _ = l.split(" ", 1)
+time = float(time)
+
+maps = {}
+
+if time <= old_time:
+    # Overwrites current values, so flush
+    d = {}
+else:
+    for key in d:
+        maps[key], = plt.plot(d[key][0], d[key][1])
+        maps[key].set_label(key)
+    plt.legend()
+
+first = l
+
+while 1:
+    if first is not None:
+        l = first
+        first = None
+    else:
+        l = sys.stdin.readline()
+
+    if l == "CLOSE":
+        import sys
+        sys.exit(0)
+    elif l == "ALGEBRAIC_LOOP":
+        continue
+    time, key, value = l.split(" ")
+    time = float(time)
+    value = float(value)
+
+    if key not in maps:
+        maps[key], = plt.plot([], [])
+        maps[key].set_label(key)
+        plt.legend()
+
+    if key not in d:
+        d[key] = ([], [])
+
+    d[key][0].append(time)
+    d[key][1].append(value)
+    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])])
+    plt.pause(0.01)
+    write_data((0.0, d))

+ 4 - 12
kernel/modelverse_jit/intrinsics.py

@@ -37,18 +37,10 @@ UNARY_INTRINSICS = {
 }
 
 CAST_INTRINSICS = {
-    'cast_i2f' : float,
-    'cast_i2s' : str,
-    'cast_i2b' : bool,
-    'cast_f2i' : int,
-    'cast_f2s' : str,
-    'cast_f2b' : bool,
-    'cast_s2i' : int,
-    'cast_s2f' : float,
-    'cast_s2b' : bool,
-    'cast_b2i' : int,
-    'cast_b2f' : float,
-    'cast_b2s' : str
+    'cast_float' : float,
+    'cast_string' : str,
+    'cast_boolean' : bool,
+    'cast_integer' : int,
 }
 
 def create_get_length(expression):

+ 48 - 45
kernel/modelverse_kernel/compiled.py

@@ -2,6 +2,51 @@ 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])]
+
+    worklist = set([name_value])
+    found = set([])
+
+    cache_value = {}
+
+    while worklist:
+        name = worklist.pop()
+        if name in found:
+            continue
+        elem, = yield [("RD", [model_dict, name])]
+        found.add(name)
+
+        # Iterate over all outgoing links
+        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])]
+            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_value = cache_value[dst]
+                worklist.add(dst_name_value)
+
+    result, = yield [("CN", [])]
+    yield [("CD", [result, i, result]) for i in found]
+
+    raise PrimitiveFinished(result)
+
 def reverseKeyLookupMulti(a, b, **remainder):
     edges, b_val, result = yield [("RO", [a]), ("RV", [b]), ("CN", [])]
     expanded_edges = yield [("RE", [i]) for i in edges]
@@ -21,6 +66,9 @@ def reverseKeyLookupMulti(a, b, **remainder):
     raise PrimitiveFinished(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])]
     options = set(edges_out) & set(edges_in)
     if options:
@@ -202,51 +250,6 @@ def set_overlap(a, b, **remainder):
 
     raise PrimitiveFinished(res)
 
-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])]
-
-    worklist = set([name_value])
-    found = set([])
-
-    cache_value = {}
-
-    while worklist:
-        name = worklist.pop()
-        if name in found:
-            continue
-        elem, = yield [("RD", [model_dict, name])]
-        found.add(name)
-
-        # Iterate over all outgoing links
-        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])]
-            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_value = cache_value[dst]
-                worklist.add(dst_name_value)
-
-    result, = yield [("CN", [])]
-    yield [("CD", [result, i, result]) for i in found]
-
-    raise PrimitiveFinished(result)
-
 def list_pop_final(a, **remainder):
     lst, = yield [("RO", [a])]
     length = len(lst)

文件差异内容过多而无法显示
+ 1261 - 0
kernel/modelverse_kernel/generated.py


+ 17 - 11
kernel/modelverse_kernel/main.py

@@ -191,13 +191,12 @@ class ModelverseKernel(object):
         # execute_jit
         task_frame, =    yield [("RD", [task_root, "frame"])]
         symbols, =       yield [("RD", [task_frame, "symbols"])]
-        all_links, =     yield [("RO", [symbols])]
-        containers =    yield [("RE", [v]) for v in all_links]
-        outgoings =     yield [("RO", [v]) for v in all_links]
-        dict_values =   yield [("RD", [v[1], "value"]) for v in containers]
-        formals_1 =     yield [("RE", [v[0]]) for v in outgoings]
-        dict_keys_ref = yield [("RD", [v[1], "name"]) for v in formals_1]
-        dict_keys =     yield [("RV", [v]) for v in dict_keys_ref]
+        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]
+
         parameters = dict(zip(dict_keys, dict_values))
 
         parameters["root"] = self.root
@@ -285,12 +284,13 @@ class ModelverseKernel(object):
         old_evalstack_link, old_phase_link, evalstack_roots = \
                             yield [("RDE", [task_frame, "evalstack"]),
                                    ("RDE", [task_frame, "phase"]),
-                                   ("RRD", [while_inst, "inst"]),
+                                   ("RRD", [while_inst, self.taskname]),
                                   ]
 
         if len(evalstack_roots) == 1:
             evalstack_root = evalstack_roots[0]
         else:
+            print("Got roots: " + str(evalstack_roots))
             raise Exception("Could not process continue statement!")
 
         prev_evalstack_roots, old_evalstack_phase_link = \
@@ -328,7 +328,7 @@ class ModelverseKernel(object):
         old_evalstack_link, old_phase_link, evalstack_roots = \
                             yield [("RDE", [task_frame, "evalstack"]),
                                    ("RDE", [task_frame, "phase"]),
-                                   ("RRD", [while_inst, "inst"]),
+                                   ("RRD", [while_inst, self.taskname]),
                                   ]
 
         if len(evalstack_roots) == 1:
@@ -503,6 +503,11 @@ class ModelverseKernel(object):
                                    ("DE", [ip_link]),
                                    ("DE", [phase_link]),
                                   ]
+
+            # Check if we already have a taskname link to the evalstack
+            links, = yield [("RD", [evalstack, self.taskname])]
+            if links is None:
+                yield [("CD", [evalstack, self.taskname, inst])]
         else:
             phase_link, new_phase = \
                             yield [("RDE", [task_frame, "phase"]),
@@ -697,6 +702,7 @@ class ModelverseKernel(object):
             if prev_frame is None:
                 _, =            yield [("DN", [task_root])]
                 del self.debug_info[self.taskname]
+                #print("Cleanup task " + str(self.taskname))
             else:
                 if self.debug_info[self.taskname]:
                     self.debug_info[self.taskname].pop()
@@ -901,8 +907,7 @@ class ModelverseKernel(object):
                                    ("RD", [inst, "last_param"]),
                                   ]
 
-            body, =         yield [("RD", [new_IP, "body"])]
-            self.jit.mark_entry_point(body)
+            self.jit.mark_entry_point(new_IP)
             
             name, =         yield [("RD", [last_param, "name"])]
             name_value, =   yield [("RV", [name])]
@@ -1089,6 +1094,7 @@ class ModelverseKernel(object):
         else:
             # No input yet, so just wait and don't advance IP or phase
             self.input_value = None
+            raise primitive_functions.SleepKernel(0.1, True)
 
     def output_init(self, task_root):
         task_frame, =   yield [("RD", [task_root, "frame"])]

+ 11 - 58
kernel/modelverse_kernel/primitives.py

@@ -138,77 +138,30 @@ def element_eq(a, b, **remainder):
     result, = yield [("CNV", [a == b])]
     raise PrimitiveFinished(result)
 
-def cast_a2s(a, **remainder):
+def cast_string(a, **remainder):
     a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [str(a_value["value"])])]
-    raise PrimitiveFinished(result)
-
-def cast_i2f(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [float(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_i2s(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [str(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_i2b(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [bool(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_f2i(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [int(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_f2s(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [str(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_f2b(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [bool(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_s2i(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [int(a_value)])]
+    if isinstance(a_value, dict):
+        result, = yield [("CNV", [str(a_value["value"])])]
+    else:
+        result, = yield [("CNV", [str(a_value)])]
     raise PrimitiveFinished(result)
 
-def cast_s2f(a, **remainder):
+def cast_float(a, **remainder):
     a_value, = yield [("RV", [a])]
     result, = yield [("CNV", [float(a_value)])]
     raise PrimitiveFinished(result)
 
-def cast_s2b(a, **remainder):
+def cast_boolean(a, **remainder):
     a_value, = yield [("RV", [a])]
     result, = yield [("CNV", [bool(a_value)])]
     raise PrimitiveFinished(result)
 
-def cast_b2i(a, **remainder):
+def cast_integer(a, **remainder):
     a_value, = yield [("RV", [a])]
     result, = yield [("CNV", [int(a_value)])]
     raise PrimitiveFinished(result)
 
-def cast_b2f(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [float(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_b2s(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", [str(a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_e2s(a, **remainder):
-    a_value, = yield [("RV", [a])]
-    result, = yield [("CNV", ["{ID: %s, value: %s}" % (a, a_value)])]
-    raise PrimitiveFinished(result)
-
-def cast_v2s(a, **remainder):
+def cast_value(a, **remainder):
     a_value, = yield [("RV", [a])]
     if isinstance(a_value, dict):
         # Action or type
@@ -218,7 +171,7 @@ def cast_v2s(a, **remainder):
     result, = yield [("CNV", [value])]
     raise PrimitiveFinished(result)
 
-def cast_id2s(a, **remainder):
+def cast_id(a, **remainder):
     result, = yield [("CNV", ["%s" % (a)])]
     raise PrimitiveFinished(result)
 
@@ -255,7 +208,7 @@ def dict_delete(a, b, **remainder):
     b_value, = yield [("RV", [b])]
     edge, = yield [("RDE", [a, b_value])]
     if edge is None:
-        print("Failed dict_delete for value %s!" % b_value)
+        print("Failed dict_delete for value '%s'!" % b_value)
         keys, = yield [("RDK", [a])]
         keys = yield [("RV", [i]) for i in keys]
         print("Keys: " + str(keys))

+ 3 - 0
kernel/modelverse_kernel/request_handler.py

@@ -278,6 +278,9 @@ class RequestHandler(object):
         except primitive_functions.PrimitiveFinished:
             self.push_generator(None)
             raise
+        except:
+            print("EXCEPTION for " + str(locals()))
+            raise
 
     def execute_call_args(self, request_args):
         """Executes a CALL_ARGS-request with the given argument list."""

文件差异内容过多而无法显示
+ 2299 - 0
kernel/rules/MvK_rules.mvc


+ 30 - 0
kernel/rules/MvK_rules_MM.mvc

@@ -0,0 +1,30 @@
+SimpleAttribute String {}
+SimpleAttribute Boolean {}
+
+Class Rule {
+    name : String
+}
+
+Class Node {
+    value? : String
+}
+
+Class Match : Node {
+    match? : Boolean
+}
+Class Create : Node {}
+Class NAC : Node {
+    match : Boolean
+}
+Class Root : Node {}
+
+Association contains (Rule, Node) {}
+
+Association Edge : Node (Node, Node) {
+    name? : String
+}
+
+Association CreateEdge : Edge (Node, Node) {}
+Association MatchEdge : Edge (Node, Node) {}
+Association DeleteEdge : MatchEdge (Node, Node) {}
+Association NACEdge : MatchEdge (Node, Node) {}

+ 6 - 0
kernel/rules/files.mvc

@@ -0,0 +1,6 @@
+SimpleAttribute String {}
+
+Class File {
+    name : String
+    content : String
+}

+ 114 - 0
kernel/rules/to_graphviz.alc

@@ -0,0 +1,114 @@
+include "primitives.alh"
+include "modelling.alh"
+include "object_operations.alh"
+include "conformance_scd.alh"
+
+Boolean function main(model : Element):
+    Element rules
+    String rule
+	String file
+	String content
+
+    rules = allInstances(model, "Rules/Rule")
+    while (set_len(rules) > 0):
+        rule = set_pop(rules)
+        content = print_rule(model, rule)
+
+		file = instantiate_node(model, "Files/File", "")
+		instantiate_attribute(model, file, "name", rule + ".dot")
+		instantiate_attribute(model, file, "content", content)
+
+    return True!
+
+String function print_rule(model : Element, rule : String):
+    String text
+    String type
+    text = ""
+
+    // Preamble
+    text = text + "digraph {\n"
+    text = text + "\tnode [shape=\"point\"]\n"
+
+    // First go through the list of all entries in the rule
+    Element nodes
+    Element edges
+    nodes = set_create()
+    edges = set_create()
+
+    Element all
+    String el
+    all = allAssociationDestinations(model, rule, "Rules/contains")
+    while (set_len(all) > 0):
+        el = set_pop(all)
+        if (is_nominal_instance(model, el, "Rules/Edge")):
+            // Is an edge
+            set_add(edges, el)
+        else:
+            // Only a node
+            set_add(nodes, el)
+
+    // Print out all the nodes in the rule
+    String node
+    while (set_len(nodes) > 0):
+        node = set_pop(nodes)
+        text = text + "\t" + string_replace(node, "/", "_") + "["
+
+        // Try to add value
+        if (element_neq(read_attribute(model, node, "value"), read_root())):
+            // Has a value, so add a label and make it oval
+            text = text + "shape=\"oval\", label=\"" + cast_string(read_attribute(model, node, "value")) + "\", "
+
+        // Add style
+        type = read_type(model, node)
+        if (type == "Rules/Match"):
+            text = text + "color=\"black\""
+        elif (type == "Rules/Root"):
+            text = text + "color=\"black\""
+        elif (type == "Rules/Create"):
+            text = text + "color=\"green\""
+        elif (type == "Rules/Delete"):
+            text = text + "color=\"blue\""
+        elif (type == "Rules/NAC"):
+            text = text + "color=\"red\""
+
+        text = text + "]\n"
+
+    // Print out all the edges in the rule
+    String edge
+    String style
+	String source
+	String destination
+    while (set_len(edges) > 0):
+        edge = set_pop(edges)
+
+        type = read_type(model, edge)
+        if (type == "Rules/MatchEdge"):
+            style = "color=\"black\""
+        elif (type == "Rules/CreateEdge"):
+            style = "color=\"green\", penwidth=4"
+        elif (type == "Rules/DeleteEdge"):
+            style = "color=\"blue\", style=\"dashed\""
+        elif (type == "Rules/NACEdge"):
+            style = "color=\"red\", style=\"dotted\""
+
+        // Try to add value
+		source = string_replace(readAssociationSource(model, edge), "/", "_")
+		destination = string_replace(readAssociationDestination(model, edge), "/", "_")
+
+        if (element_neq(read_attribute(model, edge, "value"), read_root())):
+            // Has a value, so add a label
+            text = text + "\t" + source + " -> " + destination + "["
+            text = text + style + ", label=\"" + cast_string(read_attribute(model, edge, "value")) + "\"]\n"
+        elif (set_len(allOutgoingAssociationInstances(model, edge, "")) > 0):
+            // Has no value, and we have outgoing edges ourself, so we should have an edge handle
+            text = text + "\t" + string_replace(edge, "/", "_") + "[width=0]\n"
+            text = text + "\t" + source + " -> " + string_replace(edge, "/", "_") + "[" + style + ", arrowhead=\"none\"]"
+            text = text + "\t" + string_replace(edge, "/", "_") + " -> " + destination + "[" + style + "]\n"
+        else:
+            // Has no value, meaning that we are referring to an intermediate edge...
+            text = text + "\t" + source + " -> " + destination + "[" + style + "]\n"
+
+    // Close everything
+    text = text + "}"
+
+    return text!

+ 424 - 0
kernel/rules/to_python.alc

@@ -0,0 +1,424 @@
+include "primitives.alh"
+include "modelling.alh"
+include "object_operations.alh"
+include "random.alh"
+include "utils.alh"
+
+Boolean function main(model : Element):
+	String result
+	Element nodes
+	String node
+	Element edges
+	String edge
+	String new_node
+	String source
+	String destination
+	String name
+	Element to_explore
+	Element rules
+	String rule
+	String value
+	Element explored
+	Element remainder_to_explore
+	String attr
+
+	explored = set_create()
+	result = ""
+
+	// Add the preamble...
+	result = result + "import modelverse_kernel.primitives as primitive_functions\n"
+	result = result + "\n"
+	result = result + "class ModelverseKernel(object):\n"
+	result = result + "    def __init__(self, root):\n"
+	result = result + "        self.root = root\n"
+	result = result + "        self.primitives = {}\n"
+	result = result + "        self.returnvalue = None\n"
+	result = result + "        self.success = True\n"
+	result = result + "        self.generators = {}\n"
+	result = result + "\n"
+    result = result + "    def set_overlap(self, lst):\n"
+    result = result + "        s = set(lst.pop())\n"
+    result = result + "        while (lst):\n"
+    result = result + "            s &= set(lst.pop())\n"
+    result = result + "        return list(s)\n"
+	result = result + "\n"
+	result = result + "    def execute_yields(self, taskname, operation, params, reply):\n"
+	result = result + "        try:\n"
+	result = result + "            self.success = True\n"
+	result = result + "            self.taskname = taskname\n"
+	result = result + "            if taskname not in self.generators:\n"
+	result = result + "                self.generators[taskname] = {}\n"
+	result = result + "            if operation not in self.generators[taskname]:\n"
+	result = result + "                # Create the generator for the function to execute\n"
+	result = result + "                self.generators[taskname][operation] = getattr(self, operation)(taskname, *params)\n"
+	result = result + "\n"
+	result = result + "            if reply is not None:\n"
+	result = result + "                return self.generators[taskname][operation].send(reply)\n"
+	result = result + "            else:\n"
+	result = result + "                return self.generators[taskname][operation].next()\n"
+	result = result + "        except StopIteration:\n"
+	result = result + "            # Done, so remove the generator\n"
+	result = result + "            del self.generators[taskname][operation]\n"
+	result = result + "            return None\n"
+	result = result + "        except:\n"
+	result = result + "            raise\n"
+	result = result + "\n"
+	result = result + "    ##########################\n"
+	result = result + "    ### Process primitives ###\n"
+	result = result + "    ##########################\n"
+	result = result + "    def load_primitives(self, taskname):\n"
+	result = result + "        hierarchy, =     yield [('RD', [self.root, '__hierarchy'])]\n"
+	result = result + "        primitives, =    yield [('RD', [hierarchy, 'primitives'])]\n"
+	result = result + "        keys, =          yield [('RDK', [primitives])]\n"
+	result = result + "        function_names = yield [('RV', [f]) for f in keys]\n"
+	result = result + "        signatures  =    yield [('RDN', [primitives, f]) for f in keys]\n"
+	result = result + "        bodies =         yield [('RD', [f, 'body']) for f in signatures]\n"
+	result = result + "        for i in range(len(keys)):\n"
+	result = result + "            self.primitives[bodies[i]] = getattr(primitive_functions, function_names[i])\n"
+	result = result + "\n"
+	result = result + "    ########################################\n"
+	result = result + "    ### Execute input and output methods ###\n"
+	result = result + "    ########################################\n"
+	result = result + "    def get_output(self, taskname):\n"
+	result = result + "        task_root, =        yield [('RD', [self.root, taskname])]\n"
+	result = result + "        first_output, =     yield [('RD', [task_root, 'output'])]\n"
+	result = result + "        next_output, rv =   yield [('RD', [first_output, 'next']),\n"
+	result = result + "                                   ('RD', [first_output, 'value']),\n"
+	result = result + "                                  ]\n"
+	result = result + "        if next_output is None:\n"
+	result = result + "            self.success = False\n"
+	result = result + "            self.returnvalue = None\n"
+	result = result + "        else:\n"
+	result = result + "            rv_value, =     yield [('RV', [rv])]\n"
+	result = result + "            _, _ =          yield [('CD', [task_root, 'output', next_output]),\n"
+	result = result + "                                   ('DN', [first_output]),\n"
+	result = result + "                                  ]\n"
+	result = result + "            self.returnvalue = rv_value\n"
+	result = result + "\n"
+	result = result + "    def set_input(self, taskname, value):\n"
+	result = result + "        task_root, =        yield [('RD', [self.root, taskname])]\n"
+	result = result + "        old_input, link =   yield [('RD', [task_root, 'last_input']),\n"
+	result = result + "                                   ('RDE', [task_root, 'last_input']),\n"
+	result = result + "                                  ]\n"
+	result = result + "        new_input, =        yield [('CN', [])]\n"
+	result = result + "        _, _ =              yield [('CD', [task_root, 'last_input', new_input]),\n"
+	result = result + "                                   ('CD', [old_input, 'next', new_input]),\n"
+	result = result + "                                  ]\n"
+	result = result + "\n"
+	result = result + "        new_value, =        yield [('CNV', [value])]\n"
+	result = result + "        _, _ =              yield [('CD', [old_input, 'value', new_value]),\n"
+	result = result + "                                   ('DE', [link])\n"
+	result = result + "                                  ]\n"
+	result = result + "        self.returnvalue = {'id': 100, 'value': 'success'}\n"
+	result = result + "\n"
+	result = result + "    ### Generated rules\n"
+	result = result + "    def execute_rule(self, taskname):\n"
+
+	// Done, now generate the variable code
+	result = result + "        root, = yield [('RR', [])]\n"
+	nodes = allInstances(model, "Rules/Root")
+	while (set_len(nodes) > 0):
+		node = set_pop(nodes)
+		source = string_replace(node, "/", "_")
+		result = result + "        " + source + " = root\n"
+
+		// Keep following outgoing edges to find matching nodes
+		to_explore = set_create()
+		remainder_to_explore = set_create()
+		set_add(to_explore, node)
+
+		while (set_len(to_explore) > 0):
+			// Still explore more!
+			node = set_pop(to_explore)
+			source = string_replace(node, "/", "_")
+
+			edges = allOutgoingAssociationInstances(model, node, "Rules/MatchEdge")
+			while (set_len(edges) > 0):
+				edge = set_pop(edges)
+				new_node = readAssociationDestination(model, edge)
+				if (value_eq(read_attribute(model, new_node, "match"), True)):
+					// Is a match node, so fetch the value on the edge
+					name = read_attribute(model, edge, "value")
+					destination = string_replace(new_node, "/", "_")
+
+					if (element_eq(name, read_root())):
+						String node_key
+						node_key = string_replace(set_pop(allAssociationDestinations(model, edge, "")), "/", "_")
+						if (set_in(explored, node_key)):
+							result = result + "        " + destination + ", = yield [('RDN', [" + source + ", " + node_key + "])]\n"
+						else:
+							set_add(remainder_to_explore, node)
+					else:
+						if (set_in(explored, destination)):
+							// Already visited this one in another way, so try to merge!
+							String rand
+							rand = random_string(10)
+							result = result + "        " + rand + ", = yield [('RD', [" + source + ", " + name + "])]\n"
+							result = result + "        " + "if " + rand + " != " + destination + ":\n"
+							// If the values don't agree, this is not a correct match, and we say that this element remains unmatched (i.e., assign None)
+							result = result + "            " + destination + " = None\n"
+						else:
+							// First visit to this element, so just assign
+							result = result + "        " + destination + ", = yield [('RD', [" + source + ", " + name + "])]\n"
+							set_add(explored, destination)
+
+							String value
+							value = read_attribute(model, new_node, "value")
+							if (element_neq(value, read_root())):
+								// Match node has a value we should compare as well!
+								// Read out the value from the Modelverse
+								result = result + "        " + destination + "_V, = yield [('RV', [" + destination + "])]\n"
+
+							set_add(to_explore, new_node)
+
+			if (bool_and(set_len(to_explore) == 0, set_len(remainder_to_explore) > 0)):
+				to_explore = remainder_to_explore
+				remainder_to_explore = set_create()
+
+	rules = allInstances(model, "Rules/Rule")
+	result = result + "        " + "if (False):\n"
+	result = result + "            # here to make code generation nicer...\n"
+	result = result + "            pass\n"
+	while (set_len(rules) > 0):
+		// Check if this rule is applicable
+		rule = set_pop(rules)
+
+		// Fetch all elements with a "match" label and check that they are not None (and possibly, that they have a value)
+		result = result + "        elif (True "
+		nodes = allAssociationDestinations(model, rule, "Rules/contains")
+		while (set_len(nodes) > 0):
+			node = set_pop(nodes)
+			if (value_eq(read_attribute(model, node, "match"), True)):
+				// We should match on this node:
+				value = read_attribute(model, node, "value")
+				if (bool_and(read_type(model, node) == "Rules/NAC", element_eq(value, read_root()))):
+					result = result + " and " + string_replace(node, "/", "_") + " is None "
+				else:
+					result = result + " and " + string_replace(node, "/", "_") + " is not None "
+
+				if (element_neq(value, read_root())):
+					// Got a value, so match that as well
+					// But check if it is an action element (first character == !)
+					String sign
+
+					if (read_type(model, node) == "Rules/NAC"):
+						sign = "!="
+					else:
+						sign = "=="
+
+					if (string_get(value, 0) == "!"):
+						result = result + " and isinstance(" + string_replace(node, "/", "_") + "_V , dict) and " + string_replace(node, "/", "_") + "_V['value'] " + sign + " '" + string_replace(value, "!", "") + "'"
+					elif (bool_or(bool_or(string_get(value, 0) == "'", string_get(value, 0) == "!"), bool_or(value == "True", value == "False"))):
+						result = result + " and " + string_replace(node, "/", "_") + "_V " + sign + " " + value
+
+		result = result + "):\n"
+		result = result + "            # Execute rule " + rule + "\n"
+
+		// We know all the nodes that we already have (in variable "explored")
+		// Still have to match all "match" and "delete" elements
+		// For "match", it is exactly the same as before
+		// For "delete" edges, we match using "RD" and "RDE"
+		Element create_edges
+		Element all_nodes
+		Element assigned
+
+		log("Matching rule " + rule)
+		nodes = allAssociationDestinations(model, rule, "Rules/contains")
+		all_nodes = set_overlap(nodes, allInstances(model, "Rules/Match"))
+
+		create_edges = set_create()
+		explored = set_create()
+		assigned = set_create()
+		// Username is always assigned in the beginning
+		set_add(assigned, "username")
+		set_add(assigned, "taskname")
+		while (set_len(nodes) > 0):
+			node = set_pop(nodes)
+			if (read_type(model, node) == "Rules/Root"):
+				// Found the root of this rule, so start exploring again
+			
+				// Keep following outgoing edges to find matching nodes
+				to_explore = set_create()
+				remainder_to_explore = set_create()
+				set_add(to_explore, node)
+
+				while (set_len(explored) < set_len(all_nodes)):
+					while (set_len(to_explore) > 0):
+						// Still explore more!
+						node = set_pop(to_explore)
+						log("Explore " + node)
+						set_add(explored, node)
+						source = string_replace(node, "/", "_")
+
+						edges = allOutgoingAssociationInstances(model, node, "Rules/MatchEdge")
+						while (set_len(edges) > 0):
+							edge = set_pop(edges)
+							new_node = readAssociationDestination(model, edge)
+
+							name = read_attribute(model, edge, "value")
+							destination = string_replace(new_node, "/", "_")
+
+							if (element_eq(name, read_root())):
+								String node_key
+								node_key = set_pop(allAssociationDestinations(model, edge, ""))
+								if (set_in(explored, node_key)):
+									result = result + "            " + destination + ", = yield [('RDN', [" + source + ", " + string_replace(node_key, "/", "_") + "])]\n"
+									set_add(to_explore, new_node)
+								else:
+									set_add(remainder_to_explore, node)
+									continue!
+
+								if (read_type(model, edge) == "Rules/DeleteEdge"):
+									// Delete edge
+									result = result + "            " + destination + "_DEL, = yield [('RDNE', [" + source + ", " + string_replace(node_key, "/", "_") + "])]\n"
+									result = result + "            yield [('DE', [" + destination + "_DEL])]\n"
+							else:
+								if (bool_or(string_get(name, 0) == "'", set_in(assigned, name))):
+									if (set_in(explored, new_node)):
+										// Already visited this one in another way, so try to merge!
+										String rand
+										rand = random_string(10)
+										result = result + "            " + rand + ", = yield [('RD', [" + source + ", " + name + "])]\n"
+										result = result + "            " + "if " + rand + " != " + destination + ":\n"
+										// If the values don't agree, this is not a correct match, and we say that this element remains unmatched (i.e., assign None)
+										result = result + "            " + "    " + destination + " = None\n"
+									else:
+										// First visit to this element, so just assign
+										result = result + "            " + destination + ", = yield [('RD', [" + source + ", " + name + "])]\n"
+
+										String value
+										value = read_attribute(model, new_node, "value")
+										if (element_neq(value, read_root())):
+											// Read out the value from the Modelverse, as this can be used later for reading edges
+											if (bool_and(bool_and(string_get(value, 0) != "!", string_get(value, 0) != "'"), bool_and(value != "False", value != "True"))):
+												result = result + "            " + value + ", = yield [('RV', [" + destination + "])]\n"
+												set_add(assigned, value)
+
+										set_add(to_explore, new_node)
+
+									if (read_type(model, edge) == "Rules/DeleteEdge"):
+										// Delete edge
+										result = result + "            " + destination + "_DEL, = yield [('RDE', [" + source + ", " + name + "])]\n"
+										result = result + "            yield [('DE', [" + destination + "_DEL])]\n"
+								else:
+									set_add(remainder_to_explore, node)
+
+						if (bool_and(set_len(to_explore) == 0, set_len(remainder_to_explore) > 0)):
+							to_explore = remainder_to_explore
+							remainder_to_explore = set_create()
+
+					// Check for nodes that are unexplored, but seemingly not reachable from the root directly
+					Element remaining
+					String check_elem
+					Boolean found
+					if (set_len(explored) < set_len(all_nodes)):
+						// Find all unexplored nodes
+						remaining = set_difference(all_nodes, explored)
+						log("Remain unexplored: " + set_to_string(remaining))
+						while (set_len(remaining) > 0):
+							check_elem = set_pop(remaining)
+
+							edges = allOutgoingAssociationInstances(model, check_elem, "Rules/MatchEdge")
+							found = False
+							while (set_len(edges) > 0):
+								edge = set_pop(edges)
+								new_node = readAssociationDestination(model, edge)
+								name = read_attribute(model, edge, "value")
+								if (set_in(explored, new_node)):
+									// We already explored this node, so we can do a RRD from this place!
+									if (bool_not(found)):
+										result = result + "            matched = []\n"
+									result = result + "            _tmp, = yield [('RRD', [" + string_replace(new_node, "/", "_") + ", " + name + "])]\n"
+									result = result + "            matched.append(_tmp)\n"
+									found = True
+
+							// Iterated over all edges, so check how many we found!
+							if (found):
+								set_add(to_explore, check_elem)
+								set_add(explored, check_elem)
+								// Found at least one match, so we try to find an overlapping node
+								result = result + "            " + string_replace(check_elem, "/", "_") + " = self.set_overlap(matched)[0]\n"
+
+			elif (read_type(model, node) == "Rules/Create"):
+				// A node that we should create: do that already, as otherwise we might have to sort
+				String attr
+				attr = read_attribute(model, node, "value")
+				if (element_eq(attr, read_root())):
+					// Create empty node
+					result = result + "            " + string_replace(node, "/", "_") + ", = yield [('CN', [])]\n"
+				else:
+					// Create value node
+					result = result + "            " + string_replace(node, "/", "_") + ", = yield [('CNV', [" + cast_string(attr) + "])]\n"
+			elif (read_type(model, node) == "Rules/CreateEdge"):
+				// Encounter a create edge, so alreade record this for later
+				set_add(create_edges, node)
+
+		// Now create all the new edges, given that we assume everything to be matched
+		while (set_len(create_edges) > 0):
+			edge = set_pop(create_edges)
+			attr = read_attribute(model, edge, "value")
+			if (element_neq(attr, read_root())):
+				result = result + "            " + string_replace(edge, "/", "_") + ", = yield [('CD', [" + string_replace(readAssociationSource(model, edge), "/", "_") + ", " + attr + ", " + string_replace(readAssociationDestination(model, edge), "/", "_") + "])]\n"
+			else:
+				result = result + "            " + string_replace(edge, "/", "_") + ", = yield [('CE', [" + string_replace(readAssociationSource(model, edge), "/", "_") + ", " + string_replace(readAssociationDestination(model, edge), "/", "_") + "])]\n"
+		
+	result = result + "        else:\n"
+	result = result + "            task_root, = yield [('RD', [root, taskname])]\n"
+	result = result + "            task_frame, = yield [('RD', [task_root, 'frame'])]\n"
+	result = result + "            task_IP, = yield [('RD', [task_frame, 'IP'])]\n"
+	result = result + "            task_phase, = yield [('RD', [task_frame, 'phase'])]\n"
+	result = result + "            task_phase, = yield [('RV', [task_phase])]\n"
+	result = result + "            if (task_IP is not None and task_IP in self.primitives and task_phase == 'init'):\n"
+	result = result + "                # Execute a primitive!\n"
+	result = result + "                symbols, =       yield [('RD', [task_frame, 'symbols'])]\n"
+	result = result + "                all_links, =     yield [('RO', [symbols])]\n"
+	result = result + "                containers =    yield [('RE', [v]) for v in all_links]\n"
+	result = result + "                outgoings =     yield [('RO', [v]) for v in all_links]\n"
+	result = result + "                dict_values =   yield [('RD', [v[1], 'value']) for v in containers]\n"
+	result = result + "                formals_1 =     yield [('RE', [v[0]]) for v in outgoings]\n"
+	result = result + "                dict_keys_ref = yield [('RD', [v[1], 'name']) for v in formals_1]\n"
+	result = result + "                dict_keys =     yield [('RV', [v]) for v in dict_keys_ref]\n"
+	result = result + "                parameters = dict(zip(dict_keys, dict_values))\n"
+	result = result + "                parameters['root'] = root\n"
+	result = result + "                parameters['task_root'] = task_root\n"
+	result = result + "                parameters['taskname'] = taskname\n"
+	result = result + "                parameters['mvk'] = self\n"
+	result = result + "                # prim is a generator itself!\n"
+	result = result + "                try:\n"
+	result = result + "                    # Forward the message we get to this generator\n"
+	result = result + "                    # Sometimes it might not even be a generator, in which case this should already be in the except block (i.e., for the Read Root operation)\n"
+	result = result + "                    prim = self.primitives[task_IP](**parameters)\n"
+	result = result + "                    inp = None\n"
+	result = result + "                    while 1:\n"
+	result = result + "                        inp = yield prim.send(inp)\n"
+	result = result + "                except StopIteration:\n"
+	result = result + "                    # Execution has ended without return value, so we have no idea what to do\n"
+	result = result + "                    raise Exception('Primitive finished without returning a value!')\n"
+	result = result + "                except primitive_functions.PrimitiveFinished as e:\n"
+	result = result + "                    # Execution has ended with a returnvalue, so read it out from the exception being thrown\n"
+	result = result + "                    result = e.result\n"
+	result = result + "                    #if result is None:\n"
+	result = result + "                    #    raise Exception('Primitive raised exception: value of None for operation %s with parameters %s' % (self.compiled[task_IP], str(parameters)))\n"
+	result = result + "                # Clean up the current stack, as if a return happened\n"
+	result = result + "                old_frame, =    yield [('RD', [task_frame, 'prev'])]\n"
+	result = result + "                lnk, =          yield [('RDE', [old_frame, 'returnvalue'])]\n"
+	result = result + "                _, _, _, _ =    yield [('CD', [old_frame, 'returnvalue', result]),\n"
+	result = result + "                                       ('CD', [task_root, 'frame', old_frame]),\n"
+	result = result + "                                       ('DE', [lnk]),\n"
+	result = result + "                                       ('DN', [task_frame]),\n"
+	result = result + "                                      ]\n"
+	result = result + "\n"
+	result = result + "            else:\n"
+	result = result + "                # no rules were applicable, so idle for some time\n"
+	result = result + "                pass #TODO\n"
+	result = result + "                raise primitive_functions.SleepKernel(1.0, True)\n"
+
+	log("Got result:")
+	log(result)
+
+	String file
+	file = instantiate_node(model, "Files/File", "")
+	instantiate_attribute(model, file, "name", "generated_kernel.py")
+	instantiate_attribute(model, file, "content", result)
+
+	return True!

+ 19 - 0
kernel/rules/upload.py

@@ -0,0 +1,19 @@
+import sys
+sys.path.append("wrappers")
+from modelverse import *
+
+init()
+login("admin", "admin")
+model_add("formalisms/MvK_rules_MM", "formalisms/SimpleClassDiagrams", open("kernel/rules/MvK_rules_MM.mvc", 'r').read())
+model_add("formalisms/Files", "formalisms/SimpleClassDiagrams", open("kernel/rules/files.mvc", 'r').read())
+model_add("models/MvK_rules", "formalisms/MvK_rules_MM", open("kernel/rules/MvK_rules.mvc", 'r').read())
+transformation_add_AL({"Rules": "formalisms/MvK_rules_MM"}, {"Files": "formalisms/Files"}, "models/to_python", open("kernel/rules/to_python.alc", 'r').read())
+#transformation_add_AL({"Rules": "formalisms/MvK_rules_MM"}, {"Files": "formalisms/Files"}, "models/to_graphviz", open("kernel/rules/to_graphviz.alc", 'r').read())
+transformation_add_AL({"Files": "formalisms/Files"}, {}, "models/write_files", open("kernel/rules/write_files.alc", 'r').read())
+
+print("Writing to Python...")
+transformation_execute_AL("models/to_python", {"Rules": "models/MvK_rules"}, {"Files": "models/files"})
+print("Writing to file...")
+#transformation_execute_AL("models/to_graphviz", {"Rules": "models/MvK_rules"}, {"Files": "models/files"})
+transformation_execute_AL("models/write_files", {"Files": "models/files"}, {})
+print("DONE")

+ 15 - 0
kernel/rules/write_files.alc

@@ -0,0 +1,15 @@
+include "files.alh"
+include "primitives.alh"
+include "modelling.alh"
+include "object_operations.alh"
+
+Boolean function main(model : Element):
+	Element files
+	String file
+
+	files = allInstances(model, "Files/File")
+	while (set_len(files) > 0):
+		file = set_pop(files)
+		write_file(string_replace(read_attribute(model, file, "name"), "/", "_"), read_attribute(model, file, "content"))
+
+	return True!

+ 6 - 0
kernel/test/instructions/test_instruction_call.py

@@ -145,6 +145,7 @@ class Testcall(unittest.TestCase):
         t = self.mvs.execute("CE", [self.symbols, self.val_function])
         self.mvs.execute("CE", [t, self.var_function])
         self.mvs.execute("CD", [self.params, "abc", self.var_abc])
+        self.mvs.execute("CD", [self.var_abc, "name", self.value_abc])
 
         ### Execute rules
         self.assertEquals(get_inst(self.root, self.mvs), "call")
@@ -261,6 +262,8 @@ class Testcall(unittest.TestCase):
         self.mvs.execute("CE", [t, self.var_function])
         self.mvs.execute("CD", [self.params, "a", self.var_a])
         self.mvs.execute("CD", [self.params, "b", self.var_b])
+        self.mvs.execute("CD", [self.var_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.var_b, "name", self.value_b])
 
         ### Execute rules
         self.assertEquals(get_inst(self.root, self.mvs), "call")
@@ -398,6 +401,9 @@ class Testcall(unittest.TestCase):
         self.mvs.execute("CD", [self.params, "a", self.var_a])
         self.mvs.execute("CD", [self.params, "b", self.var_b])
         self.mvs.execute("CD", [self.params, "c", self.var_c])
+        self.mvs.execute("CD", [self.var_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.var_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.var_c, "name", self.value_c])
 
         ### Execute rules
         self.assertEquals(get_inst(self.root, self.mvs), "call")

+ 56 - 67
kernel/test/primitives/test_cast.py

@@ -25,106 +25,95 @@ class TestCast(unittest.TestCase):
         execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
         self.primitives = read_primitive_interfaces(self.root, self.mvs)
 
-    def test_cast_i2f(self):
-        self.helper_primitives_1_params("cast_i2f", 2, 2.0)
+    def test_cast_float(self):
+        self.helper_primitives_1_params("cast_float", 2, 2.0)
 
-    def test_cast_i2s(self):
-        self.helper_primitives_1_params("cast_i2s", 2, "2")
+    def test_cast_string(self):
+        self.helper_primitives_1_params("cast_string", 2, "2")
 
-    def test_cast_i2b(self):
-        self.helper_primitives_1_params("cast_i2b", 2, True)
+    def test_cast_boolean(self):
+        self.helper_primitives_1_params("cast_boolean", 2, True)
 
-    def test_cast_f2i(self):
-        self.helper_primitives_1_params("cast_f2i", 2.4, 2)
+    def test_cast_integer(self):
+        self.helper_primitives_1_params("cast_integer", 2.4, 2)
 
-    def test_cast_f2s(self):
-        self.helper_primitives_1_params("cast_f2s", 2.4, "2.4")
+    def test_cast_string(self):
+        self.helper_primitives_1_params("cast_string", 2.4, "2.4")
 
-    def test_cast_f2b(self):
-        self.helper_primitives_1_params("cast_f2b", 2.4, True)
+    def test_cast_boolean(self):
+        self.helper_primitives_1_params("cast_boolean", 2.4, True)
 
-    def test_cast_s2i(self):
-        self.helper_primitives_1_params("cast_s2i", "2", 2)
+    def test_cast_integer(self):
+        self.helper_primitives_1_params("cast_integer", "2", 2)
 
-    def test_cast_s2f(self):
-        self.helper_primitives_1_params("cast_s2f", "2.4", 2.4)
+    def test_cast_float(self):
+        self.helper_primitives_1_params("cast_float", "2.4", 2.4)
 
-    def test_cast_s2b(self):
-        self.helper_primitives_1_params("cast_s2b", "2.4", True)
+    def test_cast_boolean(self):
+        self.helper_primitives_1_params("cast_boolean", "2.4", True)
 
-    def test_cast_b2i_true(self):
-        self.helper_primitives_1_params("cast_b2i", True, 1)
+    def test_cast_integer_true(self):
+        self.helper_primitives_1_params("cast_integer", True, 1)
 
-    def test_cast_b2f_true(self):
-        self.helper_primitives_1_params("cast_b2f", True, 1.0)
+    def test_cast_float_true(self):
+        self.helper_primitives_1_params("cast_float", True, 1.0)
 
-    def test_cast_b2s_true(self):
-        self.helper_primitives_1_params("cast_b2s", True, "True")
+    def test_cast_string_true(self):
+        self.helper_primitives_1_params("cast_string", True, "True")
 
-    def test_cast_b2i_false(self):
-        self.helper_primitives_1_params("cast_b2i", False, 0)
+    def test_cast_integer_false(self):
+        self.helper_primitives_1_params("cast_integer", False, 0)
 
-    def test_cast_b2f_false(self):
-        self.helper_primitives_1_params("cast_b2f", False, 0.0)
+    def test_cast_float_false(self):
+        self.helper_primitives_1_params("cast_float", False, 0.0)
 
-    def test_cast_b2s_false(self):
-        self.helper_primitives_1_params("cast_b2s", False, "False")
+    def test_cast_string_false(self):
+        self.helper_primitives_1_params("cast_string", False, "False")
 
-    def test_cast_e2s_node(self):
+    def test_cast_string_int(self):
         n = self.mvs.execute("CN", [])
-        self.helper_primitives_1_params("cast_e2s", n, "{ID: %s, value: None}" % n, t=True)
+        self.helper_primitives_1_params("cast_string", n, "None", t=True)
 
-    def test_cast_e2s_edge(self):
-        a = self.mvs.execute("CN", [])
-        b = self.mvs.execute("CN", [])
-        n = self.mvs.execute("CE", [a, b])
-        self.helper_primitives_1_params("cast_e2s", n, "{ID: %s, value: None}" % n, t=True)
-
-    def test_cast_e2s_value(self):
-        n = self.mvs.execute("CNV", [10])
-        self.helper_primitives_1_params("cast_e2s", n, "{ID: %s, value: 10}" % n, t=True)
-
-    def test_cast_v2s_int(self):
-        n = self.mvs.execute("CN", [])
-        self.helper_primitives_1_params("cast_v2s", n, "None", t=True)
+    def test_cast_string_int(self):
+        self.helper_primitives_1_params("cast_string", 2, "2")
 
-    def test_cast_v2s_int(self):
-        self.helper_primitives_1_params("cast_v2s", 2, "2")
+    def test_cast_string_neg_int(self):
+        self.helper_primitives_1_params("cast_string", -2, "-2")
 
-    def test_cast_v2s_neg_int(self):
-        self.helper_primitives_1_params("cast_v2s", -2, "-2")
+    def test_cast_string_float(self):
+        self.helper_primitives_1_params("cast_string", 2.0, "2.0")
 
-    def test_cast_v2s_float(self):
-        self.helper_primitives_1_params("cast_v2s", 2.0, "2.0")
+    def test_cast_string_neg_float(self):
+        self.helper_primitives_1_params("cast_string", -2.0, "-2.0")
 
-    def test_cast_v2s_neg_float(self):
-        self.helper_primitives_1_params("cast_v2s", -2.0, "-2.0")
+    def test_cast_string_string(self):
+        self.helper_primitives_1_params("cast_string", "abc", "abc")
 
-    def test_cast_v2s_string(self):
-        self.helper_primitives_1_params("cast_v2s", "abc", "\"abc\"")
+    def test_cast_string_string_stringnum(self):
+        self.helper_primitives_1_params("cast_value", "3", "\"3\"")
 
-    def test_cast_v2s_string_num(self):
-        self.helper_primitives_1_params("cast_v2s", "3", "\"3\"")
+    def test_cast_string_string_num(self):
+        self.helper_primitives_1_params("cast_value", 3, "3")
 
-    def test_cast_v2s_bool(self):
-        self.helper_primitives_1_params("cast_v2s", True, "true")
+    def test_cast_string_bool(self):
+        self.helper_primitives_1_params("cast_value", True, "true")
 
-    def test_cast_v2s_action(self):
-        self.helper_primitives_1_params("cast_v2s", {"value": "call"}, "call")
+    def test_cast_string_action(self):
+        self.helper_primitives_1_params("cast_value", {"value": "call"}, "call")
 
-    def test_cast_id2s_node(self):
+    def test_cast_id_node(self):
         n = self.mvs.execute("CN", [])
-        self.helper_primitives_1_params("cast_id2s", n, str(n), t=True)
+        self.helper_primitives_1_params("cast_id", n, str(n), t=True)
 
-    def test_cast_id2s_value(self):
+    def test_cast_id_value(self):
         n = self.mvs.execute("CNV", ["abc"])
-        self.helper_primitives_1_params("cast_id2s", n, str(n), t=True)
+        self.helper_primitives_1_params("cast_id", n, str(n), t=True)
 
-    def test_cast_id2s_edge(self):
+    def test_cast_id_edge(self):
         a = self.mvs.execute("CN", [])
         b = self.mvs.execute("CN", [])
         n = self.mvs.execute("CE", [a, b])
-        self.helper_primitives_1_params("cast_id2s", n, str(n), t=True)
+        self.helper_primitives_1_params("cast_id", n, str(n), t=True)
 
     def helper_primitives_1_params(self, operation, a, result, t=False):
         self.actual_arg_a = self.mvs.execute("CN", [])

+ 1 - 0
kernel/test/rules/test_rules_break.py

@@ -23,6 +23,7 @@ class Testbreak(unittest.TestCase):
         self.mvs.execute("CD", [task_frame, "evalstack", evalstack_top])
         self.mvs.execute("CD", [evalstack_top, "prev", evalstack_bottom])
         self.mvs.execute("CD", [evalstack_bottom, "inst", while_inst])
+        self.mvs.execute("CD", [evalstack_bottom, "task_1", while_inst])
         self.mvs.execute("CD", [evalstack_bottom, "phase", finish_phase])
         self.mvs.execute("CD", [root, "task_1", task_root])
         self.mvs.execute("CD", [task_root, "frame", task_frame])

+ 1 - 0
kernel/test/rules/test_rules_continue.py

@@ -23,6 +23,7 @@ class Testcontinue(unittest.TestCase):
         self.mvs.execute("CD", [task_frame, "evalstack", evalstack_top])
         self.mvs.execute("CD", [evalstack_top, "prev", evalstack_bottom])
         self.mvs.execute("CD", [evalstack_bottom, "inst", while_inst])
+        self.mvs.execute("CD", [evalstack_bottom, "task_1", while_inst])
         self.mvs.execute("CD", [evalstack_bottom, "phase", init_phase])
         self.mvs.execute("CD", [root, "task_1", task_root])
         self.mvs.execute("CD", [task_root, "frame", task_frame])

+ 6 - 1
kernel/test/rules/test_rules_input.py

@@ -1,4 +1,5 @@
 import unittest
+from modelverse_kernel.primitives import SleepKernel
 from modelverse_kernel.main import ModelverseKernel
 from utils import execute_until_finished, MvSWrapper
 
@@ -56,7 +57,11 @@ class TestInput(unittest.TestCase):
         self.mvs.execute("CD", [task_root, "input", input_queue_first])
 
         # Do the invocation until it returns None
-        execute_until_finished(self.mvk, self.mvs)
+        try:
+            execute_until_finished(self.mvk, self.mvs)
+            self.fail()
+        except SleepKernel:
+            pass
 
         # Execution of the command finished, so the MvS should be in the correct new state right now
         self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)

+ 0 - 0
kernel/test_generated/__init__.py


+ 0 - 0
kernel/test_generated/instructions/__init__.py


+ 65 - 0
kernel/test_generated/instructions/test_instruction_access.py

@@ -0,0 +1,65 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_returnvalue_ref
+
+class Testaccess(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+    def test_access(self):
+        """
+        Test the access of a variable which contains value "a"
+        """
+        self.var = self.mvs.execute("CN", [])
+        self.value = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"access"}])
+        self.resolve = self.mvs.execute("CNV", [{"value":"resolve"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+
+        self.value_a = self.mvs.execute("CNV", ["a"])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "var", self.resolve])
+        self.mvs.execute("CD", [self.resolve, "var", self.var])
+        self.mvs.execute("CD", [self.value, "value", self.const_a])
+        t = self.mvs.execute("CE", [self.symbols, self.value])
+        self.mvs.execute("CE", [t, self.var])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "eval")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.const_a)

+ 0 - 0
kernel/test_generated/instructions/test_instruction_assign.py


部分文件因为文件数量过多而无法显示