Browse Source

Initial commit from svn

Yentl Van Tendeloo 5 years ago
commit
e527d9b485
100 changed files with 19077 additions and 0 deletions
  1. 320 0
      bootstrap/bootstrap.py
  2. 63 0
      bootstrap/compilation_manager.alc
  3. 315 0
      bootstrap/conformance_scd.alc
  4. 430 0
      bootstrap/constructors.alc
  5. 37 0
      bootstrap/library.alc
  6. 195 0
      bootstrap/object_operations.alc
  7. 114 0
      bootstrap/primitives.alc
  8. 11 0
      compile.sh
  9. 13 0
      fix_linux.sh
  10. 12 0
      fix_windows.bat
  11. 2 0
      flush_compiler_caches.sh
  12. 3 0
      generate_bootstrap.sh
  13. 198 0
      hybrid_server/classes/mvkcontroller.xml
  14. 110 0
      hybrid_server/classes/server.xml
  15. 154 0
      hybrid_server/classes/socket.xml
  16. 2 0
      hybrid_server/compile.sh
  17. 17 0
      hybrid_server/python_runtime/.project
  18. 5 0
      hybrid_server/python_runtime/.pydevproject
  19. 0 0
      hybrid_server/python_runtime/__init__.py
  20. 9 0
      hybrid_server/python_runtime/accurate_time.py
  21. 58 0
      hybrid_server/python_runtime/event_queue.py
  22. 3 0
      hybrid_server/python_runtime/infinity.py
  23. 1 0
      hybrid_server/python_runtime/libs/__init__.py
  24. 59 0
      hybrid_server/python_runtime/libs/drawing.py
  25. 107 0
      hybrid_server/python_runtime/libs/ui.py
  26. 19 0
      hybrid_server/python_runtime/libs/utils.py
  27. 22 0
      hybrid_server/python_runtime/nextafter.py
  28. 941 0
      hybrid_server/python_runtime/statecharts_core.py
  29. 21 0
      hybrid_server/python_runtime/tkinter_eventloop.py
  30. 17 0
      hybrid_server/python_sccd_compiler/.project
  31. 5 0
      hybrid_server/python_sccd_compiler/.pydevproject
  32. 0 0
      hybrid_server/python_sccd_compiler/__init__.py
  33. 14 0
      hybrid_server/python_sccd_compiler/compiler_exceptions.py
  34. 911 0
      hybrid_server/python_sccd_compiler/generic_generator.py
  35. 990 0
      hybrid_server/python_sccd_compiler/generic_language_constructs.py
  36. 285 0
      hybrid_server/python_sccd_compiler/javascript_writer.py
  37. 170 0
      hybrid_server/python_sccd_compiler/lexer.py
  38. 701 0
      hybrid_server/python_sccd_compiler/old_generators/csharp_generator.py
  39. 741 0
      hybrid_server/python_sccd_compiler/old_generators/javascript_generator.py
  40. 644 0
      hybrid_server/python_sccd_compiler/old_generators/python_generator.py
  41. 81 0
      hybrid_server/python_sccd_compiler/path_calculator.py
  42. 353 0
      hybrid_server/python_sccd_compiler/python_writer.py
  43. 1131 0
      hybrid_server/python_sccd_compiler/sccd_constructs.py
  44. 129 0
      hybrid_server/python_sccd_compiler/sccdc.py
  45. 156 0
      hybrid_server/python_sccd_compiler/state_linker.py
  46. 222 0
      hybrid_server/python_sccd_compiler/stateful_writer.py
  47. 52 0
      hybrid_server/python_sccd_compiler/super_class_linker.py
  48. 118 0
      hybrid_server/python_sccd_compiler/utils.py
  49. 30 0
      hybrid_server/python_sccd_compiler/visitor.py
  50. 4 0
      hybrid_server/run.sh
  51. 19 0
      hybrid_server/run_mvk_server.py
  52. 1379 0
      hybrid_server/server.py
  53. 27 0
      hybrid_server/server.xml
  54. 117 0
      hybrid_server/socket2event.py
  55. 151 0
      integration/code/b2dc.txt
  56. 23 0
      integration/code/binary_to_decimal.alc
  57. 11 0
      integration/code/factorial.alc
  58. 11 0
      integration/code/fibonacci.alc
  59. 17 0
      integration/code/fibonacci_smart.alc
  60. 12 0
      integration/code/if_elif.alc
  61. 13 0
      integration/code/if_elif_else.alc
  62. 27 0
      integration/code/import_metamodel.alc
  63. 326 0
      integration/code/import_metamodel_cs.txt
  64. 16 0
      integration/code/leap_year.alc
  65. 4 0
      integration/code/lib_remainder.alc
  66. 6 0
      integration/code/main.alc
  67. 556 0
      integration/code/pn_interface.alc
  68. 11 0
      integration/code/power.alc
  69. 5 0
      integration/code/remainder.alc
  70. 21 0
      integration/code/revert.alc
  71. 17 0
      integration/test_binary2decimal.py
  72. 328 0
      integration/test_constructors_al.py
  73. 348 0
      integration/test_constructors_al_linkable.py
  74. 1933 0
      integration/test_constructors_models.py
  75. 17 0
      integration/test_factorial.py
  76. 17 0
      integration/test_fibonacci.py
  77. 17 0
      integration/test_fibonacci_smart.py
  78. 29 0
      integration/test_if_elif.py
  79. 17 0
      integration/test_leap_year.py
  80. 17 0
      integration/test_main.py
  81. 672 0
      integration/test_pn_interface.py
  82. 16 0
      integration/test_power.py
  83. 16 0
      integration/test_remainder.py
  84. 17 0
      integration/test_revert.py
  85. 216 0
      integration/utils.py
  86. 212 0
      interface/HUTN/grammars/actionlanguage.g
  87. 34 0
      interface/HUTN/grammars/modellanguage.g
  88. 0 0
      interface/HUTN/hutn_compiler/__init__.py
  89. 46 0
      interface/HUTN/hutn_compiler/bootstrap_visitor.py
  90. 222 0
      interface/HUTN/hutn_compiler/compiler.py
  91. 124 0
      interface/HUTN/hutn_compiler/constructors_object_visitor.py
  92. 296 0
      interface/HUTN/hutn_compiler/constructors_visitor.py
  93. 43 0
      interface/HUTN/hutn_compiler/declare_functions_visitor.py
  94. 340 0
      interface/HUTN/hutn_compiler/grammar_compiler_visitor.py
  95. 976 0
      interface/HUTN/hutn_compiler/hutnparser.py
  96. 93 0
      interface/HUTN/hutn_compiler/linker.py
  97. 78 0
      interface/HUTN/hutn_compiler/loader.py
  98. 116 0
      interface/HUTN/hutn_compiler/meta_grammar.py
  99. 73 0
      interface/HUTN/hutn_compiler/position.py
  100. 0 0
      interface/HUTN/hutn_compiler/prettyprint_visitor.py

+ 320 - 0
bootstrap/bootstrap.py

@@ -0,0 +1,320 @@
+### Configuration for creating the bootstrap model using conformance_bottom.
+
+root = ["__hierarchy"]
+
+user_data = [   "input",
+                "output",
+                "globals",
+                "frame",
+                ]
+
+user_frame = [  "evalstack",
+                "symbols",
+                "returnvalue",
+                ]
+
+primitives = {  "integer_addition": ["Integer", "Integer", "Integer"],
+                "integer_subtraction": ["Integer", "Integer", "Integer"],
+                "integer_multiplication": ["Integer", "Integer", "Integer"],
+                "integer_division": ["Integer", "Integer", "Integer"],
+                "integer_gt": ["Boolean", "Integer", "Integer"],
+                "integer_gte": ["Boolean", "Integer", "Integer"],
+                "integer_lt": ["Boolean", "Integer", "Integer"],
+                "integer_lte": ["Boolean", "Integer", "Integer"],
+                "integer_eq": ["Boolean", "Integer", "Integer"],
+                "integer_neq": ["Boolean", "Integer", "Integer"],
+                "integer_neg": ["Integer", "Integer"],
+                "float_addition": ["Float", "Float", "Float"],
+                "float_subtraction": ["Float", "Float", "Float"],
+                "float_multiplication": ["Float", "Float", "Float"],
+                "float_division": ["Float", "Float", "Float"],
+                "float_gt": ["Boolean", "Float", "Float"],
+                "float_gte": ["Boolean", "Float", "Float"],
+                "float_lt": ["Boolean", "Float", "Float"],
+                "float_lte": ["Boolean", "Float", "Float"],
+                "float_eq": ["Boolean", "Float", "Float"],
+                "float_neq": ["Boolean", "Float", "Float"],
+                "float_neg": ["Float", "Float"],
+                "bool_and": ["Boolean", "Boolean", "Boolean"],
+                "bool_or": ["Boolean", "Boolean", "Boolean"],
+                "bool_not": ["Boolean", "Boolean"],
+                "bool_eq": ["Boolean", "Boolean", "Boolean"],
+                "bool_neq": ["Boolean", "Boolean", "Boolean"],
+                "string_join": ["String", "String", "String"],
+                "string_get": ["String", "String", "Integer"],
+                "string_substr": ["String", "String", "Integer", "Integer"],
+                "string_len": ["Integer", "String"],
+                "string_split": ["Element", "String", "String"],
+                "string_startswith": ["Boolean", "String", "String"],
+                "string_eq": ["Boolean", "String", "String"],
+                "string_neq": ["Boolean", "String", "String"],
+                "action_eq": ["Boolean", "Action", "Action"],
+                "action_neq": ["Boolean", "Action", "Action"],
+                "type_eq": ["Boolean", "Type", "Type"],
+                "type_neq": ["Boolean", "Type", "Type"],
+                "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_t2s": ["String", "Type"],
+                "cast_a2s": ["String", "Action"],
+                "cast_v2s": ["String", "Element"],
+                "cast_id2s": ["String", "Element"],
+                "list_read": ["Element", "Element", "Integer"],
+                "list_append": ["Element", "Element", "Element"],
+                "list_insert": ["Element", "Element", "Integer", "Element"],
+                "list_delete": ["Element", "Element", "Integer"],
+                "list_len": ["Integer", "Element"],
+                "dict_add": ["Element", "Element", "Element", "Element"],
+                "dict_delete": ["Element", "Element", "Element"],
+                "dict_read": ["Element", "Element", "Element"],
+                "dict_read_edge": ["Element", "Element", "Element"],
+                "dict_read_node": ["Element", "Element", "Element"],
+                "dict_len": ["Integer", "Element"],
+                "dict_in": ["Boolean", "Element", "Element"],
+                "dict_in_node": ["Boolean", "Element", "Element"],
+                "dict_keys": ["Element", "Element"],
+                "set_add": ["Element", "Element", "Element"],
+                "set_pop": ["Element", "Element"],
+                "set_remove": ["Element", "Element", "Element"],
+                "set_remove_node": ["Element", "Element", "Element"],
+                "set_in": ["Boolean", "Element", "Element"],
+                "set_in_node": ["Boolean", "Element", "Element"],
+                "typeof": ["Type", "Element"],
+                "create_node": ["Element"],
+                "create_edge": ["Element", "Element", "Element"],
+                "create_value": ["Element", "Element"],
+                "is_edge": ["Boolean", "Element"],
+                "read_nr_out": ["Integer", "Element"],
+                "read_out": ["Element", "Element", "Integer"],
+                "read_nr_in": ["Integer", "Element"],
+                "read_in": ["Element", "Element", "Integer"],
+                "read_edge_src": ["Element", "Element"],
+                "read_edge_dst": ["Element", "Element"],
+                "delete_element": ["Element", "Element"],
+                "element_eq": ["Boolean", "Element", "Element"],
+                "element_neq": ["Boolean", "Element", "Element"],
+                "read_root": ["Element"],
+                "deserialize": ["Element", "String"],
+                "log": ["Element", "String"],
+            }
+
+initial_user = "user_manager"
+initial_user_code = \
+'''
+Element function read_root() = ?primitives/read_root
+Element function dict_read(a: Element, b: Element) = ?primitives/dict_read
+Element function create_node() = ?primitives/create_node
+Element function create_value(a: Element) = ?primitives/create_value
+Element function dict_add(a: Element, b: Element, c: Element) = ?primitives/dict_add
+Boolean function string_eq(a: String, b: String) = ?primitives/string_eq
+Boolean function delete_element(a: Element) = ?primitives/delete_element
+Boolean function bool_not(a: Boolean) = ?primitives/bool_not
+Boolean function dict_in(a: Element, b: Element) = ?primitives/dict_in
+
+Element function input()
+
+Void function __main():
+\tString username
+\tElement user_root
+\tElement user_frame
+\tElement output_value
+\tElement input_value
+\t
+\twhile (True):
+\t\tusername = input()
+\t\tif (string_eq(username, "__delete")):
+\t\t\tuser_root = dict_read(read_root(), input())
+\t\t\tdelete_element(user_root)
+\t\telse:
+\t\t\tif (bool_not(dict_in(read_root(), username))):
+\t\t\t\tuser_root = create_node()
+\t\t\t\tuser_frame = create_node()
+\t\t\t\toutput_value = create_node()
+\t\t\t\tinput_value = create_node()
+\t\t\t\tdict_add(user_root, "frame", user_frame)
+\t\t\t\tdict_add(user_root, "globals", create_node())
+\t\t\t\tdict_add(user_root, "output", output_value)
+\t\t\t\tdict_add(user_root, "last_output", output_value)
+\t\t\t\tdict_add(user_root, "input", input_value)
+\t\t\t\tdict_add(user_root, "last_input", input_value)
+\t\t\t\tdict_add(user_frame, "evalstack", create_node())
+\t\t\t\tdict_add(user_frame, "returnvalue", create_node())
+\t\t\t\tdict_add(user_frame, "phase", "init")
+\t\t\t\tdict_add(user_frame, "IP", dict_read(dict_read(read_root(), "__hierarchy"), "__IP"))
+\t\t\t\tdict_add(user_frame, "symbols", create_node())
+\t\t\t\t//Add this only at the end, as otherwise the user will already be detected
+\t\t\t\tdict_add(read_root(), username, user_root)
+'''
+
+code_new_users = \
+'''
+Element main
+
+include "io.alh"
+include "primitives.alc"
+include "compilation_manager.alc"
+include "constructors.alc"
+include "conformance_scd.alc"
+include "object_operations.alc"
+include "library.alc"
+
+Void function __main():
+\tInteger interface
+\twhile (True):
+\t\tinterface = input()
+\t\tif (integer_eq(interface, 0)):
+\t\t\tlog("DO deserialize")
+\t\t\texec(deserialize(input()))
+\t\telif (integer_eq(interface, 1)):
+\t\t\texec(construct_unknown())
+\t\telif (integer_eq(interface, 3)):
+\t\t\tcompilation_manager()
+\t\telse:
+\t\t\tlog("Unsupported interface!")
+'''
+
+### Actual script to generate the file
+import os
+import sys
+
+class Writer(object):
+    def __init__(self, file_a, file_b):
+        self.file_a = file_a
+        self.file_b = file_b
+
+    def write(self, text, both=True):
+        self.file_a.write(text)
+        if both:
+            self.file_b.write(text)
+
+try:
+    with open("bootstrap.m", "w") as fa:
+        with open("minimal.m", "w") as fb:
+            f = Writer(fa, fb)
+            # Create the root first
+            f.write("Node root()\n")
+
+            # Create all children of the root
+            for node in root:
+                f.write("Node %s()\n" % node)
+                f.write("Edge _%s(root, %s)\n" % (node, node))
+                f.write('Node __%s("%s")\n' % (node, node))
+                f.write("Edge ___%s(_%s, __%s)\n" % (node, node, node))
+
+            f.write("Node primitives()\n")
+            f.write("Edge _primitives(__hierarchy, primitives)\n")
+            f.write('Node __primitives("primitives")\n')
+            f.write("Edge ___primitives(_primitives, __primitives)\n")
+
+            # Define all primitive functions
+            for function, parameters in primitives.iteritems():
+                if parameters[0] == "Element":
+                    f.write("Node _type_%s()\n" % function)
+                else:
+                    f.write("Node _type_%s(%s)\n" % (function, parameters[0]))
+                    
+                f.write("Node _func_signature_%s()\n" % function)
+                f.write("Node _func_params_%s()\n" % function)
+                f.write("Node _func_body_%s()\n" % function)
+                f.write("Edge _primitives_%s(primitives, _func_signature_%s)\n" % (function, function))
+                f.write('Node _name_%s("%s")\n' % (function, function))
+                f.write("Edge _primitives_name_%s(_primitives_%s, _name_%s)\n" % (function, function, function))
+
+                f.write('Node _body_%s("body")\n' % function)
+                f.write("Edge _signature_body_%s(_func_signature_%s, _func_body_%s)\n" % (function, function, function))
+                f.write("Edge _signature_body_str_%s(_signature_body_%s, _body_%s)\n" % (function, function, function))
+
+                f.write('Node _params_%s("params")\n' % function)
+                f.write("Edge _signature_params_%s(_func_signature_%s, _func_params_%s)\n" % (function, function, function))
+                f.write("Edge _signature_params_str_%s(_signature_params_%s, _params_%s)\n" % (function, function, function))
+
+                f.write('Node _type_str_%s("type")\n' % function)
+                f.write("Edge _signature_type_%s(_func_signature_%s, _type_%s)\n" % (function, function, function))
+                f.write("Edge _signature_type_str_%s(_signature_type_%s, _type_str_%s)\n" % (function, function, function))
+
+                parameter_names = "abcdefghijklmnopqrstuvwxyz"
+                for number, param in enumerate(parameters[1:]):
+                    param_encoding = "%s_%s" % (function, parameter_names[number])
+                    if param == "Element":
+                        f.write("Node _type_%s()\n" % param_encoding)
+                    else:
+                        f.write("Node _type_%s(%s)\n" % (param_encoding, param))
+
+                    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('Node _type_str_%s("type")\n' % param_encoding)
+                    f.write("Edge _param_type_%s(_func_params_%s, _type_%s)\n" % (param_encoding, param_encoding, param_encoding))
+                    f.write("Edge _param_type_str_%s(_param_type_%s, _type_str_%s)\n" % (param_encoding, param_encoding, param_encoding))
+
+            # Create the initial user
+            f.write("Node user_root()\n")
+
+            for data in user_data:
+                f.write("Node user_%s()\n" % data)
+                f.write('Node ___user_%s("%s")\n' % (data, data))
+                f.write("Edge _user_%s(user_root, user_%s)\n" % (data, data))
+                f.write("Edge __user_%s(_user_%s, ___user_%s)\n" % (data, data, data))
+
+            for data in user_frame:
+                f.write("Node user_%s()\n" % data)
+                f.write('Node ___user_%s("%s")\n' % (data, data))
+                f.write("Edge _user_%s(user_frame, user_%s)\n" % (data, data))
+                f.write("Edge __user_%s(_user_%s, ___user_%s)\n" % (data, data, data))
+
+            # Add last_input and last_output links
+            for data in ["input", "output"]:
+                f.write('Node ___user_last_%s("last_%s")\n' % (data, data))
+                f.write("Edge _user_last_%s(user_root, user_%s)\n" % (data, data))
+                f.write("Edge __user_last_%s(_user_last_%s, ___user_last_%s)\n" % (data, data, data))
+                
+            # Bind user to the root
+            f.write('Node ___new_user("%s")\n' % initial_user)
+            f.write("Edge _new_user(root, user_root)\n")
+            f.write("Edge __new_user(_new_user, ___new_user)\n")
+
+            def compile_code_AL(code, target):
+                import sys
+                sys.path.append("../interface/HUTN/")
+                from hutn_compiler.compiler import main as compile_code
+
+                with open("bootstrap.al", "w") as f:
+                    f.write(code)
+                code = compile_code("bootstrap.al", "../interface/HUTN/grammars/actionlanguage.g", "BS", [])
+                os.remove("bootstrap.al")
+                return code.replace("auto_initial_IP", target)
+
+            # Create code for initial user
+            f.write(compile_code_AL(initial_user_code, "IP_initial"), both=False)
+            f.write('Node _IP_str("IP")\n', both=False)
+            f.write("Edge _user_frame(user_frame, IP_initial)\n", both=False)
+            f.write("Edge __user_frame(_user_frame, _IP_str)\n", both=False)
+
+            f.write('Node __phase("init")\n', both=False)
+            f.write('Node __phase_str("phase")\n', both=False)
+            f.write("Edge _user_phase(user_frame, __phase)\n", both=False)
+            f.write("Edge __user_phase(_user_phase, __phase_str)\n", both=False)
+
+            # Create code for new users to start at
+            f.write(compile_code_AL(code_new_users, "IP_new"), both=False)
+            f.write('Node __IP_str("__IP")\n', both=False)
+            f.write("Edge _user_IP(__hierarchy, IP_new)\n", both=False)
+            f.write("Edge __user_IP(_user_IP, __IP_str)\n", both=False)
+except:
+    os.remove("bootstrap.m")
+    os.remove("minimal.m")
+    raise

+ 63 - 0
bootstrap/compilation_manager.alc

@@ -0,0 +1,63 @@
+include "primitives.alh"
+include "constructors.alh"
+
+Element function compilation_manager():
+	String op_com
+	String name_com
+	Boolean defines_com
+	Element elem_com
+	Element root_com
+	Element node_com
+	Element symbols_com
+	Element keys_com
+	Integer nr_com
+	Integer i_com
+
+	if (dict_in(dict_read(read_root(), "__hierarchy"), "objects")):
+		root_com = dict_read(dict_read(read_root(), "__hierarchy"), "objects")
+	else:
+		root_com = create_node()
+		dict_add(dict_read(read_root(), "__hierarchy"), "objects", root_com)
+
+	op_com = input()
+	if (string_eq(op_com, "upload")):
+		name_com = input()
+		node_com = create_node()
+		dict_add(root_com, name_com, node_com)
+		dict_add(node_com, "hash_md5", input())
+		if (input()):
+			dict_add(node_com, "initializers", construct_top())
+		else:
+			dict_add(node_com, "initializers", deserialize(input()))
+
+		symbols_com = create_node()
+		dict_add(node_com, "symbols", symbols_com)
+		while (input()):
+			dict_add(symbols_com, input(), input())
+	elif (string_eq(op_com, "read_symbols")):
+		name_com = input()
+		node_com = dict_read(dict_read(root_com, name_com), "symbols")
+		keys_com = dict_keys(node_com)
+		String rv
+		rv = ""
+		while (integer_lt(0, read_nr_out(keys_com))):
+			elem_com = set_pop(keys_com)
+			if (dict_read(node_com, elem_com)):
+				rv = string_join(rv, string_join(elem_com, ":1\n"))
+			else:
+				rv = string_join(rv, string_join(elem_com, ":0\n"))
+		output(rv)
+	elif (string_eq(op_com, "read_initializers")):
+		node_com = dict_read(dict_read(root_com, input()), "initializers")
+		output(node_com)
+	elif (string_eq(op_com, "remove_obj")):
+		dict_delete(root_com, input())
+	elif (string_eq(op_com, "is_defined")):
+		name_com = input()
+		if (dict_in(root_com, name_com)):
+			output(dict_read(dict_read(root_com, name_com), "hash_md5"))
+		else:
+			output(create_node())
+	else:
+		log("Failed to understand command")
+	return op_com

+ 315 - 0
bootstrap/conformance_scd.alc

@@ -0,0 +1,315 @@
+include "primitives.alh"
+include "library.alh"
+include "object_operations.alh"
+include "constructors.alh"
+
+Element function set_copy(elem_to_copy : Element):
+	Element result
+	Integer counter_copy
+	Integer max
+
+	result = create_node()
+
+	// Expand the provided list by including all elements that need to be checked
+	counter_copy = 0
+	max = read_nr_out(elem_to_copy)
+	while (integer_lt(counter_copy, max)):
+		set_add(result, read_edge_dst(read_out(elem_to_copy, counter_copy)))
+		counter_copy = integer_addition(counter_copy, 1)
+
+	return result
+
+Boolean function is_direct_instance(model_idi : Element, instance_idi : Element, type_idi : Element):
+	// Just check whether or not the type mapping specifies the type as the type of the instance
+	return element_eq(dict_read_node(dict_read(model_idi, "type_mapping"), instance_idi), type_idi)
+
+Boolean function is_nominal_instance(model_ini : Element, instance_ini : Element, type_ini : Element):
+	return is_nominal_subtype(type_ini, dict_read_node(dict_read(model_ini, "type_mapping"), instance_ini), dict_read(dict_read(model_ini, "metamodel"), "type_mapping"), dict_read(model_ini, "inheritance"))
+
+Boolean function is_nominal_subtype(superclass : Element, subclass : Element, types : Element, inheritance_link : Element):
+	Integer counter_iso
+	Integer i_iso
+	Element edge_iso
+	Element destination_iso
+
+	// End of recursion
+	if (element_eq(superclass, subclass)):
+		return True
+
+	// Iterate over all superclasses of the found class
+	counter_iso = read_nr_out(subclass)
+	i_iso = 0
+	while (integer_lt(i_iso, counter_iso)):
+		edge_iso = read_out(subclass, i_iso)
+		// Check if it even has a type (to prevent errors)
+		if (dict_in_node(types, edge_iso)):
+			// Check whether it is an inheritance edge, as there is no other distinction between them
+			if (element_eq(dict_read_node(types, edge_iso), inheritance_link)):
+				// It is an inheritance edge, so follow it to its destination
+				destination_iso = read_edge_dst(edge_iso)
+				// Found a new superclass to test
+				if (is_nominal_subtype(superclass, destination_iso, types, inheritance_link)):
+					return True
+		i_iso = integer_addition(i_iso, 1)
+	
+	// No link seems to have been found, so it is False
+	return False
+
+Boolean function is_structural_instance(model_isi : Element, instance_isi : Element, type_isi : Element):
+	return is_structural_subtype(dict_read_node(dict_read(model_isi, "type_mapping"), instance_isi), type_isi)
+	
+Boolean function is_structural_subtype(subtype_isi : Element, supertype_isi : Element):
+	// Determine whether it is just the exact type or not
+	if (element_eq(subtype_isi, supertype_isi)):
+		return True
+
+	// Find all links that are required (name and type) from the specified type
+	Element required_keys_isi
+	required_keys_isi = dict_keys(supertype_isi)
+	Integer required_keys_len_isi
+	required_keys_len_isi = dict_len(required_keys_isi)
+
+	String key_isi
+	Element equivalent_isi
+	Integer i_isi
+	i_isi = 0
+
+	// Go over all keys that we require
+	while (integer_lt(i_isi, required_keys_len_isi)):
+		key_isi = set_pop(required_keys_isi)
+		// Check whether they exist in the instance
+		if (dict_in(subtype_isi, key_isi)):
+			// Normally, we should still check whether they don't violate the constraints imposed on the class (i.e., are actually present)
+			// For now, we ignore this and simply require that it is always there in the metamodel (not necessarily in the instance)
+			// TODO
+
+			// Still check whether the types match
+			if (bool_not(is_structural_subtype(dict_read(subtype_isi, key_isi), dict_read(supertype_isi, key_isi)))):
+				return False
+
+			// All clear, so pass on to the next attribute
+			i_isi = integer_addition(i_isi, 1)
+		else:
+			return False
+
+	// No violations found, so OK
+	return True
+
+String function conformance_scd(model : Element):
+	// Initialization
+	Element work_conf
+	Element model_src
+	Element metamodel_src
+	Element model_dst
+	Element metamodel_dst
+	Element models
+	Element metamodels
+	models = set_copy(dict_read(model, "model"))
+
+	Element typing
+	typing = dict_read(model, "type_mapping")
+	metamodels = set_copy(dict_read(dict_read(model, "metamodel"), "model"))
+	Element inheritance
+	inheritance = dict_read(dict_read(model, "metamodel"), "inheritance")
+	Element metamodel_typing
+	metamodel_typing = dict_read(dict_read(model, "metamodel"), "type_mapping")
+
+	// Iterate over all model elements and check if they are typed (in "typing") and their type is in the metamodel
+	while (integer_gt(dict_len(models), 0)):
+		work_conf = set_pop(models)
+		// Basic check: does the element have a type
+		if (bool_not(dict_in_node(typing, work_conf))):
+			return string_join("Model has no type specified: ", getName(model, work_conf))
+
+		// Basic check: is the type of the element part of the metamodel
+		if (bool_not(set_in_node(metamodels, dict_read_node(typing, work_conf)))):
+			return string_join("Type of element not in specified metamodel: ", getName(model, work_conf))
+
+		// Basic check: type of the value agrees with the actual type
+		// this is always checked, as it falls back to a sane default for non-values
+		if (bool_not(type_eq(dict_read_node(typing, work_conf), typeof(work_conf)))):
+			return string_join("Primitive type does not agree with actual type: ", getName(model, work_conf))
+
+		// For edges only: check whether the source is typed according to the metamodel
+		if (is_edge(work_conf)):
+			model_src = read_edge_src(work_conf)
+			metamodel_src = read_edge_src(dict_read_node(typing, work_conf))
+			if (bool_not(is_nominal_instance(model, model_src, metamodel_src))):
+				return string_join("Source of model edge not typed by source of type: ", getName(model, work_conf))
+
+		// For edges only: check whether the destination is typed according to the metamodel
+		if (is_edge(work_conf)):
+			model_dst = read_edge_dst(work_conf)
+			metamodel_dst = read_edge_dst(dict_read_node(typing, work_conf))
+			if (bool_not(is_nominal_instance(model, model_dst, metamodel_dst))):
+				return string_join("Destination of model edge not typed by destination of type: ", getName(model, work_conf))
+
+	// Structure seems fine, now do static semantics
+	if (dict_in(dict_read(model, "metamodel"), "constraints")):
+		Element constraint_function
+		constraint_function = dict_read(dict_read(model, "metamodel"), "constraints")
+		return constraint_function(model)
+	else:
+		return "OK"
+
+Element function retype(model_rt : Element, metamodel_rt : Element, inheritance_rt : Element, mapping_rt : Element):
+	if (dict_in(model_rt, "type_mapping")):
+		// Remove previous type mappings
+		dict_delete(model_rt, "type_mapping")
+	if (dict_in(model_rt, "metamodel")):
+		// Remove the previous metamodel too, as this might change too
+		dict_delete(model_rt, "metamodel")
+	if (dict_in(model_rt, "inheritance")):
+		// Remove the inheritance link too, as, yet again, this can vary
+		dict_delete(model_rt, "inheritance")
+	
+	// Start the new configuration of the metamodel and inheritance link, as well as set the new mapping relation
+	dict_add(model_rt, "metamodel", metamodel_rt)
+	dict_add(model_rt, "inheritance", inheritance_rt)
+	dict_add(model_rt, "type_mapping", mapping_rt)
+
+	return model_rt
+
+Element function add_to_model(model_atm : Element, name_atm : String, element_atm : Element):
+	if (string_eq(name_atm, "")):
+		// No name desired
+		dict_add(dict_read(model_atm, "model"), string_join("__", cast_id2s(element_atm)), element_atm)
+	else:
+		dict_add(dict_read(model_atm, "model"), name_atm, element_atm)
+	return element_atm
+
+Element function instantiate_bottom_node(model_bn : Element, name_bn : String):
+	Element new_element_bn
+	new_element_bn = create_node()
+	return add_to_model(model_bn, name_bn, new_element_bn)
+
+Element function instantiate_bottom_value(model_bv : Element, name_bv : String, value_bv : Element):
+	Element new_element_bv
+	new_element_bv = create_value(value_bv)
+	return add_to_model(model_bv, name_bv, new_element_bv)
+
+Element function instantiate_bottom_edge(model_be : Element, name_be : String, source_be : Element, target_be : Element):
+	Element new_element_be
+	new_element_be = create_edge(source_be, target_be)
+	return add_to_model(model_be, name_be, new_element_be)
+
+Element function set_model_constraints(model_con : Element, func_con : Element):
+	if (dict_in(model_con, "constraints")):
+		dict_delete(model_con, "constraints")
+	dict_add(model_con, "constraints", func_con)
+	return model_con
+
+Element function instantiate_model_lib(model_mo : Element, type_mo : Element, name_mo : String, optionals : Element, attribute_types : Element, attribute_instances : Element):
+	Element new_element_mo
+	if (is_edge(type_mo)):
+		// Create a new edge from "optionals[0]" to "optionals[1]"
+		new_element_mo = instantiate_bottom_edge(model_mo, name_mo, list_read(optionals, 0), list_read(optionals, 1))
+	else:
+		if (type_eq(typeof(type_mo), Type)):
+			new_element_mo = instantiate_bottom_value(model_mo, name_mo, list_read(optionals, 0))
+		else:
+			new_element_mo = instantiate_bottom_node(model_mo, name_mo)
+
+	// Add it to the type mapping
+	dict_add(dict_read(model_mo, "type_mapping"), new_element_mo, type_mo)
+
+	// Add all attribute types at this level
+	Integer counter_mo
+	Integer max_mo
+	Element keys_mo
+	keys_mo = dict_keys(attribute_types)
+	counter_mo = 0
+	max_mo = list_len(keys_mo)
+
+	Element attr_name_mo
+	Element attr_type_mo
+	Element created_attr_mo
+	Element created_edge_mo
+	Element metamodel_mo
+	metamodel_mo = dict_read(dict_read(model_mo, "metamodel"), "model")
+
+	// For all new attributes
+	while (integer_lt(counter_mo, max_mo)):
+		attr_name_mo = set_pop(keys_mo)
+		attr_type_mo = dict_read(attribute_types, attr_name_mo)
+
+		created_attr_mo = create_edge(new_element_mo, attr_type_mo)
+		created_edge_mo = create_edge(created_attr_mo, attr_name_mo)
+		
+		// Add it to the model
+		dict_add(dict_read(model_mo, "model"), string_join("__", cast_id2s(attr_name_mo)), attr_name_mo)
+		dict_add(dict_read(model_mo, "model"), string_join("__", cast_id2s(attr_type_mo)), attr_type_mo)
+		dict_add(dict_read(model_mo, "model"), string_join("__", cast_id2s(created_attr_mo)), created_attr_mo)
+		dict_add(dict_read(model_mo, "model"), string_join("__", cast_id2s(created_edge_mo)), created_edge_mo)
+
+		// And add the typing
+		dict_add(dict_read(model_mo, "type_mapping"), attr_name_mo, dict_read(metamodel_mo, "__String"))
+		dict_add(dict_read(model_mo, "type_mapping"), attr_type_mo, dict_read(metamodel_mo, "Type"))
+		dict_add(dict_read(model_mo, "type_mapping"), created_attr_mo, dict_read(metamodel_mo, "Attribute"))
+		dict_add(dict_read(model_mo, "type_mapping"), created_edge_mo, dict_read(metamodel_mo, "__Name"))
+
+		// Increase while loop counter
+		counter_mo = integer_addition(counter_mo, 1)
+
+	// Similarly for instantiated attributes
+	counter_mo = 0
+	keys_mo = dict_keys(attribute_instances)
+	max_mo = list_len(keys_mo)
+	Element attr_definer_class_mo
+	Element attr_type_edge_mo
+	Element attr_value_mo
+	Element attr_edge_mo
+
+	while (integer_lt(counter_mo, max_mo)):
+		// Look it up
+		attr_name_mo = set_pop(keys_mo)
+		attr_value_mo = dict_read(attribute_instances, attr_name_mo)
+		attr_definer_class_mo = find_attribute(type_mo, attr_name_mo, dict_read(dict_read(model_mo, "metamodel"), "type_mapping"), dict_read(model_mo, "inheritance"))
+		attr_type_mo = dict_read(attr_definer_class_mo, attr_name_mo)
+		attr_type_edge_mo = dict_read_edge(attr_definer_class_mo, attr_name_mo)
+		attr_edge_mo = create_edge(new_element_mo, attr_value_mo)
+
+		// Add to model
+		dict_add(dict_read(model_mo, "model"), string_join("__", cast_id2s(attr_value_mo)), attr_value_mo)
+		dict_add(dict_read(model_mo, "model"), string_join("__", cast_id2s(attr_edge_mo)), attr_edge_mo)
+
+		// Type the new elements
+		dict_add(dict_read(model_mo, "type_mapping"), attr_value_mo, attr_type_mo)
+		dict_add(dict_read(model_mo, "type_mapping"), attr_edge_mo, attr_type_edge_mo)
+
+		counter_mo = integer_addition(counter_mo, 1)
+
+	return new_element_mo
+
+Element function instantiate_new_model(metamodel_inm : Element, inheritance_inm : Element):
+	Element model_inm
+	model_inm = create_node()
+	dict_add(model_inm, "model", create_node())
+	dict_add(model_inm, "type_mapping", create_node())
+	dict_add(model_inm, "metamodel", metamodel_inm)
+	dict_add(model_inm, "inheritance", inheritance_inm)
+	return model_inm
+
+Element function generate_bottom_type_mapping(model_tm : Element):
+	Element mm_tm
+	mm_tm = dict_read(dict_read(model_tm, "metamodel"), "model")
+	dict_delete(model_tm, "type_mapping")
+	Element tm_tm
+	tm_tm = create_node()
+	dict_add(model_tm, "type_mapping", tm_tm)
+	
+	// Iterate over every element
+	Element elem_keys_tm
+	Element elem_tm
+	elem_keys_tm = dict_keys(dict_read(model_tm, "model"))
+	while (integer_lt(0, read_nr_out(elem_keys_tm))):
+		elem_tm = dict_read(dict_read(model_tm, "model"), set_pop(elem_keys_tm))
+		if (is_edge(elem_tm)):
+			dict_add(tm_tm, elem_tm, dict_read(mm_tm, "Edge"))
+		else:
+			if (string_neq(cast_v2s(elem_tm), "None")):
+				dict_add(tm_tm, elem_tm, dict_read(mm_tm, cast_v2s(typeof(elem_tm))))
+			else:
+				dict_add(tm_tm, elem_tm, dict_read(mm_tm, "Node"))
+
+	return model_tm

+ 430 - 0
bootstrap/constructors.alc

@@ -0,0 +1,430 @@
+include "primitives.alh"
+include "conformance_scd.alh"
+include "library.alh"
+include "io.alh"
+
+Element while_stack = ?
+
+Element function construct_top():
+	Element elem2
+	elem2 = input()
+	if (string_eq(elem2, "global")):
+		return construct_top_global()
+	elif (string_eq(elem2, "funcdef")):
+		return construct_top_funcdef()
+	else:
+		log(string_join("ERROR: did not understand command ", cast_e2s(elem2)))
+
+Element function construct_top_global():
+	Element this_element_tg
+	String declared_element_tg
+	String op_tg
+
+	this_element_tg = create_value(!global)
+	declared_element_tg = input()
+	dict_add(this_element_tg, "var", declared_element_tg)
+
+	// Defines
+	Element assign_tg
+	Element resolve_tg
+	Element value_tg
+	assign_tg = create_value(!assign)
+	dict_add(this_element_tg, "next", assign_tg)
+	resolve_tg = create_value(!resolve)
+	dict_add(assign_tg, "var", resolve_tg)
+	dict_add(resolve_tg, "var", declared_element_tg)
+	op_tg = input()
+	value_tg = create_value(!constant)
+	if (string_eq(op_tg, "deref")):
+		dict_add(value_tg, "node", import_node(input()))
+	elif (string_eq(op_tg, "empty")):
+		dict_add(value_tg, "node", create_node())
+	elif (string_eq(op_tg, "const")):
+		dict_add(value_tg, "node", input())
+	dict_add(assign_tg, "value", value_tg)
+
+	if (input()):
+		dict_add(assign_tg, "next", construct_top())
+	return this_element_tg
+
+Element function construct_top_funcdef():
+	Element funcdef_assign_top
+	Element funcdef_resolve_top
+	Element funcdef_constant_top
+	Element funcdef_formal_top
+	Element funcdef_func_top
+	Element funcdef_params_top
+	Element funcdef_global_top
+
+	funcdef_global_top = create_value(!global)
+	funcdef_assign_top = create_value(!assign)
+	funcdef_resolve_top = create_value(!resolve)
+	funcdef_constant_top = create_value(!constant)
+	funcdef_formal_top = input()
+	funcdef_func_top = create_node()
+	funcdef_params_top = create_node()
+	dict_add(funcdef_global_top, "var", funcdef_formal_top)
+	dict_add(funcdef_global_top, "next", funcdef_assign_top)
+	dict_add(funcdef_assign_top, "var", funcdef_resolve_top)
+	dict_add(funcdef_assign_top, "value", funcdef_constant_top)
+	dict_add(funcdef_resolve_top, "var", funcdef_formal_top)
+	dict_add(funcdef_constant_top, "node", funcdef_func_top)
+	dict_add(funcdef_func_top, "params", funcdef_params_top)
+
+	Integer funcdef_nrParams_top
+	funcdef_nrParams_top = input()
+	Integer funcdef_counter_top
+	funcdef_counter_top = 0
+	Element funcdef_param_top
+
+	String arg_names_decl_top
+	arg_names_decl_top = "abcdefghijklmnopqrstuvwxyz"
+
+	while (integer_lt(funcdef_counter_top, funcdef_nrParams_top)):
+		funcdef_param_top = create_node()
+		dict_add(funcdef_params_top, string_get(arg_names_decl_top, funcdef_counter_top), funcdef_param_top)
+		output(funcdef_param_top)
+		// Output each parameter in turn
+		funcdef_counter_top = integer_addition(funcdef_counter_top, 1)
+
+	// Now add the body
+	dict_add(funcdef_func_top, "body", construct_unknown())
+
+	if (input()):
+		dict_add(funcdef_assign_top, "next", construct_top())
+
+	return funcdef_global_top
+
+Element function construct_unknown():
+	String elem
+	Element new_model
+	Element new_model_model
+	elem = input()
+
+	if (string_eq(elem, "if")):
+		return construct_if()
+	elif (string_eq(elem, "while")):
+		return construct_while()
+	elif (string_eq(elem, "access")):
+		return construct_access()
+	elif (string_eq(elem, "resolve")):
+		return construct_resolve()
+	elif (string_eq(elem, "assign")):
+		return construct_assign()
+	elif (string_eq(elem, "call")):
+		return construct_call()
+	elif (string_eq(elem, "return")):
+		return construct_return()
+	elif (string_eq(elem, "const")):
+		return construct_const()
+	elif (string_eq(elem, "declare")):
+		return construct_declare()
+	elif (string_eq(elem, "global")):
+		return construct_global()
+	elif (string_eq(elem, "funcdef")):
+		return construct_funcdef()
+	elif (string_eq(elem, "output")):
+		return construct_output()
+	elif (string_eq(elem, "input")):
+		return construct_input()
+	elif (string_eq(elem, "deref")):
+		return construct_deref()
+	elif (string_eq(elem, "break")):
+		return construct_break()
+	elif (string_eq(elem, "continue")):
+		return construct_continue()
+	elif (string_eq(elem, "tag")):
+		Element tmp_constructed
+		tmp_constructed = construct_unknown()
+		output(tmp_constructed)
+		return tmp_constructed
+	elif (string_eq(elem, "instantiate_bottom")):
+		new_model = create_node()
+		dict_add(new_model, "model", create_node())
+		instantiate_bottom(new_model)
+		output(new_model)
+		return construct_unknown()
+	elif (string_eq(elem, "instantiate_model")):
+		new_model = instantiate_new_model(input(), dict_read(dict_read(input(), "model"), input()))
+		instantiate_model(new_model)
+		output(new_model)
+		return construct_unknown()
+	elif (string_eq(elem, "retype_model")):
+		retype_model(input())
+		return construct_unknown()
+	else:
+		log(string_join("ERROR: did not understand command ", cast_e2s(elem)))
+
+Element function construct_if():
+	Element this_element_1
+	this_element_1 = create_value(!if)
+	dict_add(this_element_1, "cond", construct_unknown())
+	dict_add(this_element_1, "then", construct_unknown())
+	if (input()):
+		dict_add(this_element_1, "else", construct_unknown())
+	if (input()):
+		dict_add(this_element_1, "next", construct_unknown())
+	return this_element_1
+
+Element function construct_while():
+	Element this_element_2
+	this_element_2 = create_value(!while)
+	dict_add(this_element_2, "cond", construct_unknown())
+
+	list_append(while_stack, this_element_2)
+	dict_add(this_element_2, "body", construct_unknown())
+	list_delete(while_stack, integer_subtraction(list_len(while_stack), 1))
+
+	if (input()):
+		dict_add(this_element_2, "next", construct_unknown())
+	return this_element_2
+
+Element function construct_access():
+	Element this_element_3
+	this_element_3 = create_value(!access)
+	dict_add(this_element_3, "var", construct_unknown())
+	return this_element_3
+
+Element function construct_resolve():
+	Element this_element_4
+	this_element_4 = create_value(!resolve)
+	dict_add(this_element_4, "var", input())
+	return this_element_4
+
+Element function construct_assign():
+	Element this_element_5
+	this_element_5 = create_value(!assign)
+	dict_add(this_element_5, "var", construct_unknown())
+	dict_add(this_element_5, "value", construct_unknown())
+	if (input()):
+		dict_add(this_element_5, "next", construct_unknown())
+	return this_element_5
+
+Element function construct_call():
+	Element this_element_6
+	this_element_6 = create_value(!call)
+	dict_add(this_element_6, "func", construct_unknown())
+
+	Integer nrParams
+	nrParams = input()
+	Integer counter
+	counter = 0
+
+	Element param
+	Element prev_param
+	String arg_names_call
+	arg_names_call = "abcdefghijklmnopqrstuvwxyz"
+
+	while (integer_lt(counter, nrParams)):
+		param = create_node()
+
+		dict_add(param, "name", string_get(arg_names_call, counter))
+		dict_add(param, "value", construct_unknown())
+
+		if (integer_eq(counter, 0)):
+			dict_add(this_element_6, "params", param)
+		else:
+			dict_add(prev_param, "next_param", param)
+		prev_param = param
+
+		counter = integer_addition(counter, 1)
+
+	if (integer_gt(nrParams, 0)):
+		dict_add(this_element_6, "last_param", prev_param)
+
+	if (input()):
+		dict_add(this_element_6, "next", construct_unknown())
+	return this_element_6
+
+Element function construct_return():
+	Element this_element_7
+	this_element_7 = create_value(!return)
+	if (input()):
+		dict_add(this_element_7, "value", construct_unknown())
+	return this_element_7
+
+Element function construct_const():
+	Element this_element_8
+	this_element_8 = create_value(!constant)
+	dict_add(this_element_8, "node", input())
+	return this_element_8
+
+Element function construct_declare():
+	Element this_element_9
+	Element declared_element_1
+	this_element_9 = create_value(!declare)
+	declared_element_1 = create_node()
+	dict_add(this_element_9, "var", declared_element_1)
+	output(declared_element_1)
+	if (input()):
+		dict_add(this_element_9, "next", construct_unknown())
+	return this_element_9
+
+// TODO remove global keyword
+Element function construct_global():
+	Element this_element_10
+	String declared_element_2
+	this_element_10 = create_value(!global)
+	declared_element_2 = input()
+	dict_add(this_element_10, "var", declared_element_2)
+	if (input()):
+		dict_add(this_element_10, "next", construct_unknown())
+	return this_element_10
+
+Element function construct_input():
+	Element this_element_11
+	this_element_11 = create_value(!input)
+	return this_element_11
+
+Element function construct_output():
+	Element this_element_12
+	this_element_12 = create_value(!output)
+	dict_add(this_element_12, "value", construct_unknown())
+	if (input()):
+		dict_add(this_element_12, "next", construct_unknown())
+	return this_element_12
+
+Element function construct_deref():
+	Element this_element_13
+	this_element_13 = create_value(!constant)
+	dict_add(this_element_13, "node", import_node(input()))
+	return this_element_13
+
+Element function construct_funcdef():
+	Element funcdef_assign
+	Element funcdef_resolve
+	Element funcdef_constant
+	Element funcdef_formal
+	Element funcdef_func
+	Element funcdef_params
+
+	funcdef_assign = create_value(!assign)
+	funcdef_resolve = create_value(!resolve)
+	funcdef_constant = create_value(!constant)
+	funcdef_formal = input()
+	funcdef_func = create_node()
+	funcdef_params = create_node()
+	dict_add(funcdef_assign, "var", funcdef_resolve)
+	dict_add(funcdef_assign, "value", funcdef_constant)
+	dict_add(funcdef_resolve, "var", funcdef_formal)
+	dict_add(funcdef_constant, "node", funcdef_func)
+	dict_add(funcdef_func, "params", funcdef_params)
+
+	Integer funcdef_nrParams
+	funcdef_nrParams = input()
+	Integer funcdef_counter
+	funcdef_counter = 0
+	Element funcdef_param
+
+	String arg_names_decl
+	arg_names_decl = "abcdefghijklmnopqrstuvwxyz"
+
+	while (integer_lt(funcdef_counter, funcdef_nrParams)):
+		funcdef_param = create_node()
+		dict_add(funcdef_params, string_get(arg_names_decl, funcdef_counter), funcdef_param)
+		output(funcdef_param)
+		// Output each parameter in turn
+		funcdef_counter = integer_addition(funcdef_counter, 1)
+
+	// Now add the body
+	dict_add(funcdef_func, "body", construct_unknown())
+
+	if (input()):
+		dict_add(funcdef_assign, "next", construct_unknown())
+
+	return funcdef_assign
+
+Element function construct_break():
+	Element this_element_15
+	this_element_15 = create_value(!break)
+	dict_add(this_element_15, "while", dict_read(while_stack, integer_subtraction(list_len(while_stack), 1)))
+	return this_element_15
+
+Element function construct_continue():
+	Element this_element_16
+	this_element_16 = create_value(!continue)
+	dict_add(this_element_16, "while", dict_read(while_stack, integer_subtraction(list_len(while_stack), 1)))
+	return this_element_16
+
+Element function instantiate_bottom(model_18 : Element):
+	Element this_element_18
+	Element bottom_type
+	bottom_type = input()
+	String element_name_18
+	element_name_18 = input()
+
+	// Find out which kind of element we want to create
+	if (string_eq(bottom_type, "node")):
+		instantiate_bottom_node(model_18, element_name_18)
+	elif (string_eq(bottom_type, "value")):
+		instantiate_bottom_value(model_18, element_name_18, input())
+	elif (string_eq(bottom_type, "edge")):
+		instantiate_bottom_edge(model_18, element_name_18, dict_read(dict_read(model_18, "model"), input()), dict_read(dict_read(model_18, "model"), input()))
+
+	// If there is more to come, we also add these elements
+	if (input()):
+		return instantiate_bottom(model_18)
+	else:
+		return model_18
+
+Element function instantiate_model(model_19 : Element):
+	Element type_19
+	type_19 = dict_read(dict_read(dict_read(model_19, "metamodel"), "model"), input())
+
+	Element name_19
+	name_19 = input()
+
+	Element params_19
+	params_19 = create_node()
+	if (is_edge(type_19)):
+		list_append(params_19, dict_read(dict_read(model_19, "model"), input()))
+		list_append(params_19, dict_read(dict_read(model_19, "model"), input()))
+	elif (type_eq(typeof(type_19), Type)):
+		list_append(params_19, input())
+
+	Element attribute_types_19
+	attribute_types_19 = create_node()
+	while (input()):
+		dict_add(attribute_types_19, input(), input())
+
+	Element attribute_instances_19
+	attribute_instances_19 = create_node()
+	while (input()):
+		dict_add(attribute_instances_19, input(), input())
+
+	instantiate_model_lib(model_19, type_19, name_19, params_19, attribute_types_19, attribute_instances_19)
+
+	if (input()):
+		instantiate_model(model_19)
+	
+	return 1
+
+Element function retype_model(model_20 : Element):
+	Element metamodel_20
+	metamodel_20 = input()
+
+	Element inheritance_20
+	inheritance_20 = dict_read(dict_read(input(), "model"), input())
+
+	Element mapping_20
+	mapping_20 = create_node()
+	while (input()):
+		dict_add(mapping_20, dict_read(dict_read(model_20, "model"), input()), dict_read(dict_read(metamodel_20, "model"), input()))
+
+	return retype(model_20, metamodel_20, inheritance_20, mapping_20)
+
+Element function find_attribute(source_21 : Element, attr_name_21 : Element, types_21 : Element, inheritance_link_21 : Element):
+	if (dict_in(source_21, attr_name_21)):
+		return source_21
+	else:
+		Integer counter_21
+		Integer i
+		Element edge
+		counter_21 = read_nr_out(source_21)
+		i = 0
+		while (integer_lt(i, counter_21)):
+			edge = read_out(source_21, i)
+			if (element_eq(dict_read_node(types_21, edge), inheritance_link_21)):
+				return find_attribute(read_edge_dst(edge), attr_name_21, types_21, inheritance_link_21)
+			i = integer_addition(i, 1)
+		// No return at the moment, as this crashes the MvK

+ 37 - 0
bootstrap/library.alc

@@ -0,0 +1,37 @@
+include "primitives.alh"
+
+Element function export_node(model_name_ex : String, model_reference : Element):
+	Element splitted_ex
+	splitted_ex = string_split(model_name_ex, "/")
+	Integer length_ex
+	length_ex = integer_subtraction(list_len(splitted_ex), 1)
+	Integer counter_i_ex
+	counter_i_ex = 0
+	Element current_ex
+	current_ex = dict_read(read_root(), "__hierarchy")
+	while(integer_lt(counter_i_ex, length_ex)):
+		if (bool_not(dict_in(current_ex, list_read(splitted_ex, counter_i_ex)))):
+			// Create it first
+			dict_add(current_ex, list_read(splitted_ex, counter_i_ex), create_node())
+		current_ex = dict_read(current_ex, list_read(splitted_ex, counter_i_ex))
+		counter_i_ex = integer_addition(counter_i_ex, 1)
+	
+	// current now contains the place where we should add the element
+	dict_add(current_ex, list_read(splitted_ex, length_ex), model_reference)
+
+	return model_reference
+
+Element function import_node(model_name_im : String):
+	Element splitted_im
+	splitted_im = string_split(model_name_im, "/")
+	Integer length_im
+	length_im = list_len(splitted_im)
+	Integer counter_i_im
+	counter_i_im = 0
+	Element current_im
+	current_im = dict_read(read_root(), "__hierarchy")
+	while (integer_lt(counter_i_im, length_im)):
+		current_im = dict_read(current_im, list_read(splitted_im, counter_i_im))
+		counter_i_im = integer_addition(counter_i_im, 1)
+
+	return current_im

+ 195 - 0
bootstrap/object_operations.alc

@@ -0,0 +1,195 @@
+include "primitives.alh"
+include "conformance_scd.alh"
+include "constructors.alh"
+
+Element function allInstances(model_ai : Element, type_ai : Element):
+	Element type_mapping_ai
+	Element result_ai
+
+	type_mapping_ai = dict_read(model_ai, "type_mapping")
+	result_ai = create_node()
+
+	Integer counter_ai
+	counter_ai = 0
+
+	Integer length_ai
+	length_ai = read_nr_out(type_mapping_ai)
+
+	Element edge_ai
+	while (integer_lt(counter_ai, length_ai)):
+		edge_ai = read_out(type_mapping_ai, counter_ai)
+		if (element_eq(read_edge_dst(edge_ai), type_ai)):
+			// Found an element of the specified type
+			set_add(result_ai, read_edge_dst(read_out(edge_ai, 0)))
+		counter_ai = integer_addition(counter_ai, 1)
+	
+	return result_ai
+
+Element function allOutgoingAssociationInstances(model_aoai : Element, source_aoai : Element, assoc_aoai : Element):
+	// Read out all outgoing edges of the model and select those that are typed by the specified association
+	// TODO for some reason this crashes if allInstances is used!
+	Integer length_aoai
+	length_aoai = read_nr_out(source_aoai)
+
+	Integer counter_aoai
+	counter_aoai = 0
+
+	Element result_aoai
+	result_aoai = create_node()
+
+	Element edge_aoai
+	while (integer_lt(counter_aoai, length_aoai)):
+		edge_aoai = read_out(source_aoai, counter_aoai)
+		if (element_eq(dict_read_node(dict_read(model_aoai, "type_mapping"), edge_aoai), assoc_aoai)):
+			set_add(result_aoai, edge_aoai)
+		counter_aoai = integer_addition(counter_aoai, 1)
+	return result_aoai
+
+Element function allIncomingAssociationInstances(model_aiai : Element, source_aiai : Element, assoc_aiai : Element):
+	// Read out all outgoing edges of the model and select those that are typed by the specified association
+	Element result_aiai
+	result_aiai = create_node()
+	Element allinsts_aiai
+	allinsts_aiai = allInstances(model_aiai, assoc_aiai)
+
+	Element understudy_aiai
+	while (integer_lt(0, read_nr_out(allinsts_aiai))):
+		understudy_aiai = set_pop(allinsts_aiai)
+		if (element_eq(read_edge_dst(understudy_aiai), source_aiai)):
+			set_add(result_aiai, understudy_aiai)
+	return result_aiai
+
+Element function readElementByName(model_rebn : Element, name_rebn : String):
+	return dict_read(dict_read(model_rebn, "model"), name_rebn)
+
+Element function findAttribute(source_fa : Element, attr_name_fa : Element, types_fa : Element, inheritance_link_fa : Element):
+	if (dict_in(source_fa, attr_name_fa)):
+		return dict_read_edge(source_fa, attr_name_fa)
+	else:
+		Integer counter_fa
+		Integer i_fa
+		Element edge_fa
+		counter_fa = read_nr_out(source_fa)
+		i_fa = 0
+		while (integer_lt(i_fa, counter_fa)):
+			edge_fa = read_out(source_fa, i_fa)
+			if (element_eq(dict_read_node(types_fa, edge_fa), inheritance_link_fa)):
+				return find_attribute(read_edge_dst(edge_fa), attr_name_fa, types_fa, inheritance_link_fa)
+			i_fa = integer_addition(i_fa, 1)
+		// No return at the moment, as this crashes the MvK
+		log("ERROR: could not find attribute")
+
+Element function readAttribute(model_ra : Element, source_ra : Element, attr_name_ra : String):
+	// Read out the edge we are talking about
+	Element edge_ra
+	edge_ra = findAttribute(dict_read_node(dict_read(model_ra, "type_mapping"), source_ra), attr_name_ra, dict_read(model_ra, "type_mapping"), dict_read(model_ra, "inheritance"))
+
+	return read_edge_dst(set_pop(allOutgoingAssociationInstances(model_ra, source_ra, edge_ra)))
+
+Element function setAttribute(model_sa : Element, source_sa : Element, attr_name_sa : String, value_sa : Element):
+	// Read out which edge we are talking about
+	Element edge_sa
+	edge_sa = deleteAttribute(model_sa, source_sa, attr_name_sa)
+
+	// Now make the element
+	Element created_edge_sa
+	created_edge_sa = create_edge(source_sa, value_sa)
+	dict_add(dict_read(model_sa, "type_mapping"), created_edge_sa, edge_sa)
+	dict_add(dict_read(model_sa, "type_mapping"), value_sa, read_edge_dst(edge_sa))
+	add_to_model(model_sa, "", value_sa)
+	add_to_model(model_sa, "", created_edge_sa)
+
+	return True
+
+Element function deleteAttribute(model_da : Element, source_da : Element, attr_name_da : Element):
+	Element edge_da
+	edge_da = findAttribute(dict_read_node(dict_read(model_da, "type_mapping"), source_da), attr_name_da, dict_read(model_da, "type_mapping"), dict_read(model_da, "inheritance"))
+
+	Element found_elements_da
+	found_elements_da = allOutgoingAssociationInstances(model_da, source_da, edge_da)
+
+	Element rm_element_da
+	if (integer_gt(list_len(found_elements_da), 0)):
+		rm_element_da = read_edge_dst(set_pop(found_elements_da))
+		dict_delete(dict_read(model_da, "type_mapping"), rm_element_da)
+		delete_element(rm_element_da)
+
+	return edge_da
+
+Element function getAttributeList(model_gali : Element, mm_gali : Element):
+	Element result_gali
+	result_gali = create_node()
+	// Get all outgoing "dictionary" links
+	Element set_gali_own
+	set_gali_own = dict_keys(mm_gali)
+
+	// Filter them
+	Element e_gali
+	while (integer_lt(0, read_nr_out(set_gali_own))):
+		e_gali = set_pop(set_gali_own)
+		if (type_eq(typeof(e_gali), String)):
+			if (type_eq(typeof(dict_read(mm_gali, e_gali)), Type)):
+				// This is a primitive type, so add to the list
+				dict_add(result_gali, e_gali, dict_read(mm_gali, e_gali))
+
+	// And go up to the possible supertypes
+	Element found_elements_gali
+	found_elements_gali = allOutgoingAssociationInstances(model_gali, mm_gali, dict_read(model_gali, "inheritance"))
+	Element dict_gali_super
+	Integer i_gali
+	Integer max_gali
+	Element set_gali_super
+	Element found_key_gali
+	while (integer_lt(0, read_nr_out(found_elements_gali))):
+		// Now find the destination of these associations, which are the superclasses of this model
+		dict_gali_super = getAttributeList(model_gali, read_edge_dst(set_pop(found_elements_gali)))
+		set_gali_super = dict_keys(dict_gali_super)
+		// Merge the two
+		while (integer_lt(0, read_nr_out(set_gali_super))):
+			found_key_gali = set_pop(set_gali_super)
+			dict_add(result_gali, found_key_gali, dict_read(dict_gali_super, found_key_gali))
+
+	return result_gali
+
+Element function getInstantiatableAttributes(model_gili : Element, element_gili : Element):
+	Element result_gili
+	result_gili = create_node()
+	// Get all outgoing "dictionary" links
+	Element set_gili_own
+	set_gili_own = dict_keys(element_gili)
+
+	// Filter them
+	Element e_gili
+	while (integer_lt(0, read_nr_out(set_gili_own))):
+		e_gili = set_pop(set_gili_own)
+		if (bool_and(type_eq(typeof(e_gili), String), type_eq(typeof(dict_read(element_gili, e_gili)), Type))):
+			// This is a primitive type, so add to the list
+			dict_add(result_gili, e_gili, dict_read(element_gili, e_gili))
+
+	return result_gili
+
+String function getName(m : Element, e : Element):
+	Element element_keys
+	Element s
+	s = dict_read(m, "model")
+	element_keys = dict_keys(s)
+
+	while (integer_lt(0, read_nr_out(element_keys))):
+		Element key
+		key = set_pop(element_keys)
+		if (element_eq(dict_read_node(s, key), e)):
+			return key
+
+	return string_join(string_join("(unknown: ", cast_e2s(e)), " )")
+
+String function reverseNameLookup(s_rnl : Element, e_rnl : Element):
+	Element element_keys_rnl
+	element_keys_rnl = dict_keys(s_rnl)
+
+	while (integer_lt(0, read_nr_out(element_keys_rnl))):
+		Element key_rnl
+		key_rnl = set_pop(element_keys_rnl)
+		if (element_eq(dict_read_node(s_rnl, key_rnl), e_rnl)):
+			return key_rnl
+
+	return string_join(string_join("(unknown: ", cast_e2s(e_rnl)), " )")

+ 114 - 0
bootstrap/primitives.alc

@@ -0,0 +1,114 @@
+Boolean function action_eq(a: Action, b: Action) = ?primitives/action_eq
+Boolean function action_neq(a: Action, b: Action) = ?primitives/action_neq
+Boolean function bool_and(a: Boolean, b: Boolean) = ?primitives/bool_and
+Boolean function bool_or(a: Boolean, b: Boolean) = ?primitives/bool_or
+Boolean function bool_not(a: Boolean) = ?primitives/bool_not
+Boolean function bool_eq(a: Boolean, b: Boolean) = ?primitives/bool_eq
+Boolean function bool_neq(a: Boolean, b: Boolean) = ?primitives/bool_neq
+Element function create_node() = ?primitives/create_node
+Element function create_edge(a: Element, b: Element) = ?primitives/create_edge
+Element function create_value(a: Element)  = ?primitives/create_value
+Boolean function is_edge(a: Element)  = ?primitives/is_edge
+Integer function read_nr_out(a: Element)  = ?primitives/read_nr_out
+Element function read_out(a: Element, b: Integer)  = ?primitives/read_out
+Integer function read_nr_in(a: Element)  = ?primitives/read_nr_in
+Element function read_in(a: Element, b: Integer)  = ?primitives/read_in
+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
+Boolean function element_neq(a: Element, b: Element)  = ?primitives/element_neq
+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_t2s(a: Type)  = ?primitives/cast_t2s
+String function cast_v2s(a: Element)  = ?primitives/cast_v2s
+String function cast_id2s(a: Element)  = ?primitives/cast_id2s
+Element function dict_add(a: Element, b: Element, c: Element) = ?primitives/dict_add
+Element function dict_delete(a: Element, b: Element) = ?primitives/dict_delete
+Element function dict_read(a: Element, b: Element)  = ?primitives/dict_read
+Element function dict_read_edge(a: Element, b: Element)  = ?primitives/dict_read_edge
+Element function dict_read_node(a: Element, b: Element)  = ?primitives/dict_read_node
+Integer function dict_len(a: Element)  = ?primitives/dict_len
+Boolean function dict_in(a: Element, b: Element)  = ?primitives/dict_in
+Boolean function dict_in_node(a: Element, b: Element)  = ?primitives/dict_in_node
+Element function dict_keys(a: Element)  = ?primitives/dict_keys
+Float function float_addition(a: Float, b: Float) = ?primitives/float_addition
+Float function float_subtraction(a: Float, b: Float)  = ?primitives/float_subtraction
+Float function float_multiplication(a: Float, b: Float)  = ?primitives/float_multiplication
+Float function float_division(a: Float, b: Float)  = ?primitives/float_division
+Boolean function float_gt(a: Float, b: Float)  = ?primitives/float_gt
+Boolean function float_gte(a: Float, b: Float)  = ?primitives/float_gte
+Boolean function float_lt(a: Float, b: Float)  = ?primitives/float_lt
+Boolean function float_lte(a: Float, b: Float)  = ?primitives/float_lte
+Boolean function float_eq(a: Float, b: Float)  = ?primitives/float_eq
+Boolean function float_neq(a: Float, b: Float)  = ?primitives/float_neq
+Boolean function float_neg(a: Float) = ?primitives/float_neg
+Integer function integer_addition(a: Integer, b: Integer) = ?primitives/integer_addition
+Integer function integer_subtraction(a: Integer, b: Integer)  = ?primitives/integer_subtraction
+Integer function integer_multiplication(a: Integer, b: Integer)  = ?primitives/integer_multiplication
+Integer function integer_division(a: Integer, b: Integer)  = ?primitives/integer_division
+Boolean function integer_gt(a: Integer, b: Integer)  = ?primitives/integer_gt
+Boolean function integer_gte(a: Integer, b: Integer)  = ?primitives/integer_gte
+Boolean function integer_lt(a: Integer, b: Integer)  = ?primitives/integer_lt
+Boolean function integer_lte(a: Integer, b: Integer)  = ?primitives/integer_lte
+Boolean function integer_eq(a: Integer, b: Integer)  = ?primitives/integer_eq
+Boolean function integer_neq(a: Integer, b: Integer)  = ?primitives/integer_neq
+Boolean function integer_neg(a: Integer) = ?primitives/integer_neg
+Element function list_read(a: Element, b: Integer) = ?primitives/list_read
+Element function list_append(a: Element, b: Element)  = ?primitives/list_append
+Element function list_insert(a: Element, b: Element, c: Integer)  = ?primitives/list_insert
+Element function list_delete(a: Element, b: Integer)  = ?primitives/list_delete
+Integer function list_len(a: Element)  = ?primitives/list_len
+Element function set_add(a: Element, b: Element)  = ?primitives/set_add
+Element function set_pop(a: Element)  = ?primitives/set_pop
+Element function set_remove(a: Element, b: Element)  = ?primitives/set_remove
+Boolean function set_in(a: Element, b: Element)  = ?primitives/set_in
+Element function set_remove_node(a: Element, b: Element)  = ?primitives/set_remove_node
+Element function set_in_node(a: Element, b: Element)  = ?primitives/set_in_node
+String function string_join(a: String, b: String)  = ?primitives/string_join
+String function string_get(a: String, b: Integer)  = ?primitives/string_get
+String function string_substr(a: String, b: Integer, c: Integer)  = ?primitives/string_substr
+Integer function string_len(a: String)  = ?primitives/string_len
+Boolean function string_eq(a: String, b: String)  = ?primitives/string_eq
+Boolean function string_neq(a: String, b: String)  = ?primitives/string_neq
+Element function string_split(a: String, b: String)  = ?primitives/string_split
+Boolean function string_startswith(a: String, b: String)  = ?primitives/string_startswith
+Boolean function type_eq(a: Type, b: Type)  = ?primitives/type_eq
+Boolean function type_neq(a: Type, b: Type)  = ?primitives/type_neq
+Type function typeof(a: Element)  = ?primitives/typeof
+Element function deserialize(a: String)  = ?primitives/deserialize
+Element function log(a: String) = ?primitives/log
+Element function read_root() = ?primitives/read_root
+
+Element function exec(first_instr : Element):
+	// This does very ugly things, so beware!
+	// Basically, we dynamically construct an if True condition with as body the provided instructions
+	//  after the if conditional, we append a return of an empty element, as we need a return at the end
+	//  returns in the code are therefore allowed (and will be the return value), but not necessarily
+	Element n
+	n = create_node()
+	dict_add(n, "params", create_node())
+	Element exec_if
+	exec_if = create_value(!if)
+	Element exec_const_true
+	exec_const_true = create_value(!constant)
+	dict_add(exec_const_true, "node", create_value(True))
+	dict_add(exec_if, "cond", exec_const_true)
+	dict_add(exec_if, "then", first_instr)
+	dict_add(n, "body", exec_if)
+	Element exec_return
+	exec_return = create_value(!return)
+	dict_add(exec_if, "next", exec_return)
+	return n()

+ 11 - 0
compile.sh

@@ -0,0 +1,11 @@
+#!/bin/bash
+set -e
+
+source library.sh
+
+# Leave this here too, as the call might crash early
+curl http://localhost:8001 -d "op=set_input&username=user_manager&element_type=V&value=\"$2\"" -s -S >> /dev/null
+
+f=`realpath $1`
+cd interface/HUTN
+${python} hutn_compiler/compiler.py $f grammars/actionlanguage.g ${4-PO} $2 $3 $f

+ 13 - 0
fix_linux.sh

@@ -0,0 +1,13 @@
+#!/bin/bash
+ln -s ../utils.py kernel/test/functions/utils.py
+ln -s ../utils.py kernel/test/instructions/utils.py
+ln -s ../utils.py kernel/test/primitives/utils.py
+ln -s ../utils.py kernel/test/rules/utils.py
+
+ln -s ../util.py interface/HUTN/test/grammar_action_language/util.py
+ln -s ../util.py interface/HUTN/test/graph_compilation_action_language/util.py
+
+ln -s ../../state/mvs_server/primitives.mvi interface/HUTN/primitives.mvi
+ln -s ../../state/mvs_server/primitives.mvs interface/HUTN/primitives.mvs
+ln -s ../../state/mvs_server/primitives.mvi kernel/test/primitives.mvi
+ln -s ../../state/mvs_server/primitives.mvs kernel/test/initial.mvs

+ 12 - 0
fix_windows.bat

@@ -0,0 +1,12 @@
+copy kernel\test\utils.py kernel\test\functions\utils.py
+copy kernel\test\utils.py kernel\test\instructions\utils.py
+copy kernel\test\utils.py kernel\test\primitives\utils.py
+copy kernel\test\utils.py kernel\test\rules\utils.py
+
+copy interface\HUTN\test\util.py interface\HUTN\test\grammar_action_language\util.py
+copy interface\HUTN\test\util.py interface\HUTN\test\graph_compilation_action_language\util.py
+
+copy state\mvs_server\primitives.mvi interface\HUTN\primitives.mvi
+copy state\mvs_server\primitives.mvs interface\HUTN\primitives.mvs
+copy state\mvs_server\primitives.mvi kernel\test\primitives.mvi
+copy state\mvs_server\primitives.mvs kernel\test\initial.mvs

+ 2 - 0
flush_compiler_caches.sh

@@ -0,0 +1,2 @@
+#!/bin/bash
+find . -type f -name '*.pickle' -delete

+ 3 - 0
generate_bootstrap.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+cd bootstrap
+pypy bootstrap.py

+ 198 - 0
hybrid_server/classes/mvkcontroller.xml

@@ -0,0 +1,198 @@
+<class name="MvKController">
+    <relationships>
+        <association name="to_mvi" class="Server" min="1" max="1"/>
+    </relationships>
+    <constructor>
+        <parameter name="params"/>
+        <body>
+            <![CDATA[
+            self.mvs = ModelverseState("../bootstrap/bootstrap.m")
+            self.root = self.mvs.read_root()[0]
+            self.mvk = ModelverseKernel(self.root)
+            self.all_failed = False
+            self.timeout = False
+
+            self.users = set()
+            self.input_queue = defaultdict(list)
+            self.output_queue = defaultdict(list)
+            self.source = None
+
+            self.mvs_operations = {
+                    "CN": self.mvs.create_node,
+                    "CE": self.mvs.create_edge,
+                    "CNV": self.mvs.create_nodevalue,
+                    "CD": self.mvs.create_dict,
+
+                    "RV": self.mvs.read_value,
+                    "RO": self.mvs.read_outgoing,
+                    "RI": self.mvs.read_incoming,
+                    "RE": self.mvs.read_edge,
+                    "RD": self.mvs.read_dict,
+                    "RDN": self.mvs.read_dict_node,
+                    "RDNE": self.mvs.read_dict_node_edge,
+                    "RDE": self.mvs.read_dict_edge,
+                    "RRD": self.mvs.read_reverse_dict,
+                    "RR": self.mvs.read_root,
+                    "RDK": self.mvs.read_dict_keys,
+
+                    "DE": self.mvs.delete_edge,
+                    "DN": self.mvs.delete_node,
+                }
+
+            self.execute_modelverse("", "load_primitives", [])
+            ]]>
+        </body>
+    </constructor>
+
+    <method name="execute_modelverse">
+        <parameter name="username"/>
+        <parameter name="operation"/>
+        <parameter name="params"/>
+        <body>
+            <![CDATA[
+            reply = None
+            commands = []
+            while 1:
+                commands = self.mvk.execute_yields(username, operation, params, reply)
+                if commands is None:
+                    break
+                reply = [self.mvs_operations[command[0]](*(command[1]))[0] for command in commands]
+                if len(reply) == 1:
+                    reply = reply[0]
+            ]]>
+        </body>
+    </method>
+
+    <scxml initial="init_server">
+        <state id="init_server">
+            <onentry>
+                <raise scope="cd" event="create_instance">
+                    <parameter expr="'to_mvi'"/>
+                    <parameter expr="'Server'"/>
+                    <parameter expr="''"/>
+                    <parameter expr="8001"/>
+                </raise>
+            </onentry>
+            <transition event="instance_created" target="../running">
+                <parameter name="instancename"/>
+                <raise scope="cd" event="start_instance">
+                    <parameter expr="instancename"/>
+                </raise>
+            </transition>
+        </state>
+
+        <parallel id="running">
+            <state id="wait_for_requests">
+                <state id="wait">
+                    <transition event="from_mvi" target=".">
+                        <parameter name="source"/>
+                        <parameter name="data"/>
+                        <script>
+                            # No JSON encoding necessary, as it is not complex
+                            try:
+                                if data["op"] == "set_input":
+                                    if "element_type" in data:
+                                        if data["element_type"] == "V":
+                                            value = json.loads(data["value"])
+                                        else:
+                                            value = data["value"]
+                                        args = [data["element_type"], value]
+                                        self.input_queue[data["username"]].append((source, [args]))
+                                    else:
+                                        d = []
+                                        for t, v in json.loads(data["data"]):
+                                            if t == "V":
+                                                v = json.loads(v)
+                                            d.append([t, v])
+                                        self.input_queue[data["username"]].append((source, d))
+                                elif data["op"] == "get_output":
+                                    self.output_queue[data["username"]].append(source)
+                                else:
+                                    print("DROPPING unknown operation: " + str(data["op"]))
+                            except:
+                                print("DROPPING deserialization error")
+                        </script>
+                    </transition>
+                </state>
+            </state>
+
+            <state id="execution">
+                <state id="execution">
+                    <onentry>
+                        <script>
+                            self.timeout = False
+                            self.destination = None
+                            if self.users:
+                                user = self.users.pop()
+
+                                # Check if there are values to input
+                                if self.input_queue[user]:
+                                    source, args = self.input_queue[user].pop(0)
+                                    for args_entry in args:
+                                        self.execute_modelverse(user, "set_input", args_entry)
+
+                                    self.destination = source
+                                    self.value = {"id": 200, "value": "OK"}
+                                    self.all_failed = False
+
+                                # Now process for some steps, or until we are again blocked for input
+                                for x in xrange(200):
+                                    self.execute_modelverse(user, "execute_rule", [])
+
+                                    if not self.mvk.success:
+                                        # Blocking or broken, so quit already to stop wasting CPU
+                                        break
+
+                                    self.all_failed = False
+
+                                # Check that we don't have anything to output yet, otherwise we wait
+                                if self.destination is None:
+                                    # Perform output if there is anything
+                                    if self.output_queue[user]:
+                                        self.execute_modelverse(user, "get_output", [])
+                                        if self.mvk.success:
+                                            self.destination = self.output_queue[user].pop(0)
+                                            self.value = self.mvk.returnvalue
+                                            self.all_failed = False
+                            else:
+                                out = self.mvs.read_outgoing(self.root)[0]
+                                for m in out:
+                                    src, user = self.mvs.read_edge(m)[0]
+                                    outgoing = self.mvs.read_outgoing(m)[0]
+                                    first = self.mvs.read_edge(outgoing[0])[0]
+                                    dest = first[1]
+                                    name = self.mvs.read_value(dest)[0]
+                                    if name.startswith("__"):
+                                        continue
+                                    self.users.add(name)
+                                self.timeout = self.all_failed
+                                self.all_failed = True
+                        </script>
+                    </onentry>
+
+                    <transition cond="self.destination is not None" after="0" target=".">
+                        <raise event="HTTP_input" scope="narrow" target="'to_mvi/%s' % self.destination">
+                            <parameter expr="self.value"/>
+                        </raise>
+                    </transition>
+
+                    <transition cond="self.timeout and self.destination is None" after="0.1" target="."/>
+
+                    <transition cond="not self.timeout and self.destination is None" after="0" target="."/>
+                </state>
+            </state>
+
+            <state id="remove_sockets">
+                <state id="remove_sockets">
+                    <transition event="delete_socket" target=".">
+                        <parameter name="socket"/>
+                        <script>
+                            for user in self.output_queue.keys():
+                                self.output_queue[user] = [s for s in self.output_queue[user] if s != socket]
+                        </script>
+                    </transition>
+                </state>
+            </state>
+        </parallel>
+    </scxml>
+</class>

+ 110 - 0
hybrid_server/classes/server.xml

@@ -0,0 +1,110 @@
+<class name="Server">
+    <relationships>
+        <association name="sockets" class="Socket"/>
+        <association name="parent" class="MvKController" min="1" max="1"/>
+    </relationships>
+    <constructor>
+        <parameter name="address"/>
+        <parameter name="port"/>
+        <body>
+            <![CDATA[
+            self.socket = None
+            self.address = address
+            self.port = port
+            ]]>
+        </body>
+    </constructor>
+
+    <scxml initial="main">
+        <parallel id="main">
+            <state id="forward">
+                <state id="forward">
+                    <transition event="HTTP_output" target=".">
+                        <parameter name="association_name"/>
+                        <parameter name="data"/>
+                        <raise event="from_mvi" scope="narrow" target="'parent'">
+                            <parameter expr="association_name"/>
+                            <parameter expr="data"/>
+                        </raise>
+                    </transition>
+                </state>
+            </state>
+
+            <state id="server" initial="init">
+                <state id="init">
+                    <onentry>
+                        <raise scope="output" event="create_socket" port="socket_out"/>
+                    </onentry>
+                    <transition port="socket_in" event="created_socket" target="../binding">
+                        <parameter name="socket"/>
+                        <script>
+                            self.socket = socket
+                        </script>
+                    </transition>
+                </state>
+                <state id="binding">
+                    <onentry>
+                        <raise scope="output" event="bind_socket" port="socket_out">
+                            <parameter expr="self.socket"/>
+                            <parameter expr="(self.address, self.port)"/>
+                        </raise>
+                    </onentry>
+                    <transition port="socket_in" event="bound_socket" cond="self.socket == socket" target="../listening">
+                        <parameter name="socket"/>
+                    </transition>
+                </state>
+                <state id="listening">
+                    <onentry>
+                        <raise scope="output" event="listen_socket" port="socket_out">
+                            <parameter expr="self.socket"/>
+                        </raise>
+                    </onentry>
+                    <transition port="socket_in" event="listened_socket" cond="self.socket == socket" target="../accepting">
+                        <parameter name="socket"/>
+                        <raise scope="output" port="socket_out" event="accept_socket">
+                            <parameter expr="self.socket"/>
+                        </raise>
+                    </transition>
+                </state>
+                <state id="accepting">
+                    <transition port="socket_in" event="accepted_socket" target=".">
+                        <parameter name="socket"/>
+                        <parameter name="connected_socket"/>
+                        <raise scope="cd" event="create_instance">
+                            <parameter expr="'sockets'" />
+                            <parameter expr="'Socket'" />
+                            <parameter expr="connected_socket" />
+                        </raise>
+                        <raise scope="output" port="socket_out" event="accept_socket">
+                            <parameter expr="self.socket"/>
+                        </raise>
+                    </transition>
+                    <transition event="instance_created" target=".">
+                        <parameter name="instancename"/>
+                        <raise scope="cd" event="start_instance">
+                            <parameter expr="instancename" />
+                        </raise>
+                        <raise scope="narrow" event="set_association_name" target="instancename">
+                            <parameter expr="instancename"/>
+                        </raise>
+                    </transition>
+                    <transition after="1.0" target="."/>
+                </state>
+            </state>
+
+            <state id="close_socket">
+                <state id="close">
+                    <transition event="close_socket" target=".">
+                        <parameter name="association_name"/>
+                        <raise scope="cd" event="delete_instance">
+                            <parameter expr="association_name"/>
+                        </raise>
+                        <raise scope="broad" event="delete_socket">
+                            <parameter expr="association_name"/>
+                        </raise>
+                    </transition>
+                </state>
+            </state>
+        </parallel>
+    </scxml>
+</class>

+ 154 - 0
hybrid_server/classes/socket.xml

@@ -0,0 +1,154 @@
+<class name="Socket">
+    <relationships>
+        <association name="parent" class="Server" min="1" max="1"/>
+    </relationships>
+
+    <constructor>
+        <parameter name="my_socket"/>
+        <body>
+            <![CDATA[
+            self.socket = my_socket
+            self.received_data = ""
+            self.send_data = ""
+            self.closed = False
+            self.association_name = None
+            ]]>
+        </body>
+    </constructor>
+    <scxml initial="init">
+        <state id="init">
+            <transition event="set_association_name" target="../connected">
+                <parameter name="association_name"/>
+                <script>
+                    self.association_name = association_name
+                </script>
+            </transition>
+        </state>
+        <parallel id="connected">
+            <state id="listening" initial="listen">
+                <state id="listen">
+                    <onentry>
+                        <raise scope="output" port="socket_out" event="recv_socket">
+                            <parameter expr="self.socket"/>
+                        </raise>
+                    </onentry>
+                    <transition event="received_socket" port="socket_in" cond="(self.socket == socket) and (len(data) > 0)" target=".">
+                        <parameter name="socket"/>
+                        <parameter name="data"/>
+                        <script>
+                            self.received_data += data
+                        </script>
+                        <raise event="received_data"/>
+                    </transition>
+                    <transition event="received_socket" port="socket_in" cond="(self.socket == socket) and (len(data) == 0)" target="../closed">
+                        <parameter name="socket"/>
+                        <parameter name="data"/>
+                        <raise event="received_data"/>
+                    </transition>
+                </state>
+                <state id="closed">
+                    <onentry>
+                        <script>
+                            self.closed = True
+                        </script>
+                    </onentry>
+                </state>
+            </state>
+
+            <state id="sending" initial="waiting_for_data">
+                <state id="waiting_for_data">
+                    <transition cond="len(self.send_data) > 0" target="../transferring">
+                        <raise scope="output" port="socket_out" event="send_socket">
+                            <parameter expr="self.socket"/>
+                            <parameter expr="self.send_data"/>
+                        </raise>
+                    </transition>
+                </state>
+                <state id="transferring">
+                    <transition event="sent_socket" port="socket_in" cond="self.socket == socket" target="../waiting_for_data">
+                        <parameter name="socket"/>
+                        <parameter name="sent_bytes"/>
+                        <script>
+                            self.send_data = self.send_data[sent_bytes:]
+                        </script>
+                    </transition>
+                </state>
+            </state>
+
+            <state id="queueing">
+                <state id="queueing">
+                    <transition event="HTTP_input" target=".">
+                        <parameter name="data"/>
+                        <script>
+                            #post_data = "&amp;".join(["%s=%s" % (urllib.quote(k), urllib.quote(v)) for k, v in data.iteritems()])
+                            post_data = "&amp;".join(["%s=%s" % (k, v) for k, v in data.iteritems()])
+                            self.send_data += "HTTP/1.0 200 OK\r\n"
+                            self.send_data += "Content-Length: %s\r\n" % len(post_data)
+                            self.send_data += "Content-Type: %s; charset=UTF-8\r\n" % "text/plain"
+                            self.send_data += "\r\n"
+                            self.send_data += str(post_data)
+                        </script>
+                    </transition>
+                </state>
+            </state>
+
+            <state id="parsing" initial="wait_for_header">
+                <state id="wait_for_header">
+                    <transition cond="'\r\n\r\n' in self.received_data and self.received_data.startswith('POST')" target="../wait_for_payload">
+                        <script>
+                            header, self.received_data = self.received_data.split("\r\n\r\n", 1)
+                            header = header.lower()
+                            if "content-length" in header:
+                                _, after = header.split("content-length:", 1)
+                                after = after.split("\r\n", 1)[0]
+                                after = after.strip()
+                                self.length = int(after)
+                            else:
+                                self.length = float('inf')
+                        </script>
+                    </transition>
+                    <transition cond="self.closed and len(self.received_data) == 0" target="../closing"/>
+                </state>
+                <state id="closing">
+                    <transition after="0.0" target=".">
+                        <raise event="close"/>
+                    </transition>
+                </state>
+                <state id="wait_for_payload">
+                    <transition cond="len(self.received_data) >= self.length or self.closed" target="../wait_for_header">
+                        <script>
+                            if self.length == float('inf'):
+                                data = self.received_data
+                                self.received_data = ""
+                            else:
+                                data = self.received_data[:self.length]
+                                self.received_data = self.received_data[self.length:]
+
+                            # We support POST data only, so everything is in the data
+                            try:
+                                params = dict([p.split('=') for p in data.split('&amp;')])
+                                data = {k: urllib.unquote_plus(v) for k, v in params.iteritems()}
+                            except:
+                                data = {}
+                        </script>
+                        <raise event="HTTP_output" scope="narrow" target="'parent'">
+                            <parameter expr="self.association_name"/>
+                            <parameter expr="data"/>
+                        </raise>
+                    </transition>
+                </state>
+            </state>
+            <transition event="close" target="../close"/>
+        </parallel>
+        <state id="close">
+            <onentry>
+                <raise port="socket_out" event="close_socket">
+                    <parameter expr="self.socket"/>
+                </raise>
+                <raise scope="narrow" target="'parent'" event="close_socket">
+                    <parameter expr="self.association_name"/>
+                </raise>
+            </onentry>
+        </state>
+    </scxml>
+</class>

+ 2 - 0
hybrid_server/compile.sh

@@ -0,0 +1,2 @@
+#!/bin/bash
+python python_sccd_compiler/sccdc.py -p threads server.xml

+ 17 - 0
hybrid_server/python_runtime/.project

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

+ 5 - 0
hybrid_server/python_runtime/.pydevproject

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

+ 0 - 0
hybrid_server/python_runtime/__init__.py


+ 9 - 0
hybrid_server/python_runtime/accurate_time.py

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

+ 58 - 0
hybrid_server/python_runtime/event_queue.py

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

+ 3 - 0
hybrid_server/python_runtime/infinity.py

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

+ 1 - 0
hybrid_server/python_runtime/libs/__init__.py

@@ -0,0 +1 @@
+

+ 59 - 0
hybrid_server/python_runtime/libs/drawing.py

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

+ 107 - 0
hybrid_server/python_runtime/libs/ui.py

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

+ 19 - 0
hybrid_server/python_runtime/libs/utils.py

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

+ 22 - 0
hybrid_server/python_runtime/nextafter.py

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

+ 941 - 0
hybrid_server/python_runtime/statecharts_core.py

@@ -0,0 +1,941 @@
+import abc
+import re
+from accurate_time import time
+import threading
+import traceback
+import math
+from nextafter import nextafter
+from infinity import INFINITY
+from event_queue import EventQueue
+from Queue import Queue, Empty
+
+class RuntimeException(Exception):
+	def __init__(self, message):
+		self.message = message
+	def __str__(self):
+		return repr(self.message)
+
+class AssociationException(RuntimeException):
+	pass
+
+class AssociationReferenceException(RuntimeException):
+	pass
+
+class ParameterException(RuntimeException):
+	pass
+
+class InputException(RuntimeException):
+	pass
+
+class Association(object):
+	#wrapper object for one association relation
+	def __init__(self, to_class, min_card, max_card):
+		self.to_class = to_class
+		self.min_card = min_card
+		self.max_card = max_card
+		self.instances = {}  # maps index (as string) to instance
+		self.instances_to_ids = {}
+		self.size = 0
+		self.next_id = 0
+		
+
+	def allowedToAdd(self):
+		return self.max_card == -1 or self.size < self.max_card
+		
+	def allowedToRemove(self):
+		return self.min_card == -1 or self.size > self.min_card
+		
+	def addInstance(self, instance):
+		if self.allowedToAdd() :
+			new_id = self.next_id
+			self.next_id += 1
+			self.instances[new_id] = instance
+			self.instances_to_ids[instance] = new_id
+			self.size += 1
+			return new_id
+		else :
+			raise AssociationException("Not allowed to add the instance to the association.")
+		
+	def removeInstance(self, instance):
+		if self.allowedToRemove() :
+			del self.instances[self.instances_to_ids[instance]]
+			del self.instances_to_ids[instance]
+			self.size -= 1
+		else :
+			raise AssociationException("Not allowed to remove the instance from the association.")
+		
+	def getInstance(self, index):
+		try :
+			return self.instances[index]
+		except IndexError :
+			raise AssociationException("Invalid index for fetching instance(s) from association.")
+
+"""class InstanceWrapper(object):
+	#wrapper object for an instance and its relevant information needed in the object manager
+	def __init__(self, instance, associations):
+		self.instance = instance
+		self.associations = {}
+		for association in associations :
+			self.associations[association.getName()] = association  
+		
+	def getAssociation(self, name):
+		try :
+			return self.associations[name]
+		except KeyError :
+			raise AssociationReferenceException("Unknown association %s." % name)
+	
+	def getInstance(self):
+		return self.instance"""
+
+class ObjectManagerBase(object):
+	__metaclass__  = abc.ABCMeta
+	
+	def __init__(self, controller):
+		self.controller = controller
+		self.events = EventQueue()
+		self.instances = set() #a dictionary that maps RuntimeClassBase to InstanceWrapper
+		
+	def addEvent(self, event, time_offset = 0.0):
+		self.events.add(event, time_offset)
+		
+	# Broadcast an event to all instances
+	def broadcast(self, new_event):
+		for i in self.instances:
+			i.addEvent(new_event)
+		
+	def getWaitTime(self):  
+		#first get waiting time of the object manager's events
+		smallest_time = self.events.getEarliestTime()
+		#check all the instances
+		for instance in self.instances:
+			smallest_time = min(smallest_time, instance.getEarliestEventTime())
+		return smallest_time
+	
+	def stepAll(self, delta):
+		self.step(delta)
+		for i in self.instances:
+			i.step(delta)
+
+	def step(self, delta):
+		self.events.decreaseTime(delta)
+		for event in self.events.popDueEvents() :
+			self.handleEvent(event)
+			   
+	def start(self):
+		for i in self.instances:
+			i.start()		  
+			   
+	def handleEvent(self, e):   
+		if e.getName() == "narrow_cast" :
+			self.handleNarrowCastEvent(e.getParameters())
+			
+		elif e.getName() == "broad_cast" :
+			self.handleBroadCastEvent(e.getParameters())
+			
+		elif e.getName() == "create_instance" :
+			self.handleCreateEvent(e.getParameters())
+			
+		elif e.getName() == "associate_instance" :
+			self.handleAssociateEvent(e.getParameters())
+			
+		elif e.getName() == "start_instance" :
+			self.handleStartInstanceEvent(e.getParameters())
+			
+		elif e.getName() == "delete_instance" :
+			self.handleDeleteInstanceEvent(e.getParameters())
+			
+	def processAssociationReference(self, input_string):
+		if len(input_string) == 0 :
+			raise AssociationReferenceException("Empty association reference.")
+		regex_pattern = re.compile("^([a-zA-Z_]\w*)(?:\[(\d+)\])?$")
+		path_string =  input_string.split("/")
+		result = []
+		for piece in path_string :
+			match = regex_pattern.match(piece)
+			if match :
+				name = match.group(1)
+				index = match.group(2)
+				if index is None :
+					index = -1
+				result.append((name,int(index)))
+			else :
+				raise AssociationReferenceException("Invalid entry in association reference. Input string: " + input_string)
+		return result
+	
+	def handleStartInstanceEvent(self, parameters):
+		if len(parameters) != 2 :
+			raise ParameterException ("The start instance event needs 2 parameters.")  
+		else :
+			source = parameters[0]
+			traversal_list = self.processAssociationReference(parameters[1])
+			for i in self.getInstances(source, traversal_list) :
+				i["instance"].start()
+			source.addEvent(Event("instance_started", parameters = [parameters[1]]))
+		
+	def handleBroadCastEvent(self, parameters):
+		if len(parameters) != 1 :
+			raise ParameterException ("The broadcast event needs 1 parameter.")
+		self.broadcast(parameters[0])
+
+	def handleCreateEvent(self, parameters):
+		if len(parameters) < 2 :
+			raise ParameterException ("The create event needs at least 2 parameters.")
+
+		source = parameters[0]
+		association_name = parameters[1]
+		
+		association = source.associations[association_name]
+		#association = self.instances_map[source].getAssociation(association_name)
+		if association.allowedToAdd() :
+			''' allow subclasses to be instantiated '''
+			class_name = association.to_class if len(parameters) == 2 else parameters[2]
+			new_instance = self.createInstance(class_name, parameters[3:])
+			if not new_instance:
+				raise ParameterException("Creating instance: no such class: " + class_name)
+			#index = association.addInstance(new_instance)
+			try:
+				index = association.addInstance(new_instance)
+			except AssociationException as exception:
+				raise RuntimeException("Error adding instance to association '" + association_name + "': " + str(exception))
+			p = new_instance.associations.get("parent")
+			if p:
+				p.addInstance(source)
+			source.addEvent(Event("instance_created", None, [association_name+"["+str(index)+"]"]))
+		else :
+			source.addEvent(Event("instance_creation_error", None, [association_name]))
+
+	def handleDeleteInstanceEvent(self, parameters):
+		if len(parameters) < 2 :
+			raise ParameterException ("The delete event needs at least 2 parameters.")
+		else :
+			source = parameters[0]
+			association_name = parameters[1]
+			traversal_list = self.processAssociationReference(association_name)
+			instances = self.getInstances(source, traversal_list)
+			#association = self.instances_map[source].getAssociation(traversal_list[0][0])
+			association = source.associations[traversal_list[0][0]]
+			for i in instances:
+				try:
+					association.removeInstance(i["instance"])
+					self.instances.discard(i["instance"])
+				except AssociationException as exception:
+					raise RuntimeException("Error removing instance from association '" + association_name + "': " + str(exception))
+				i["instance"].stop()
+				#if hasattr(i.instance, 'user_defined_destructor'):
+				i["instance"].user_defined_destructor()
+			source.addEvent(Event("instance_deleted", parameters = [parameters[1]]))
+				
+	def handleAssociateEvent(self, parameters):
+		if len(parameters) != 3 :
+			raise ParameterException ("The associate_instance event needs 3 parameters.")
+		else :
+			source = parameters[0]
+			to_copy_list = self.getInstances(source,self.processAssociationReference(parameters[1]))
+			if len(to_copy_list) != 1 :
+				raise AssociationReferenceException ("Invalid source association reference.")
+			wrapped_to_copy_instance = to_copy_list[0]["instance"]
+			dest_list = self.processAssociationReference(parameters[2])
+			if len(dest_list) == 0 :
+				raise AssociationReferenceException ("Invalid destination association reference.")
+			last = dest_list.pop()
+			if last[1] != -1 :
+				raise AssociationReferenceException ("Last association name in association reference should not be accompanied by an index.")
+				
+			for i in self.getInstances(source, dest_list) :
+				i["instance"].associations[last[0]].addInstance(wrapped_to_copy_instance)
+		
+	def handleNarrowCastEvent(self, parameters):
+		if len(parameters) != 3 :
+			raise ParameterException ("The associate_instance event needs 3 parameters.")
+		source = parameters[0]
+		traversal_list = self.processAssociationReference(parameters[1])
+		cast_event = parameters[2]
+		for i in self.getInstances(source, traversal_list) :
+			i["instance"].addEvent(cast_event)
+		
+	def getInstances(self, source, traversal_list):
+		currents = [{
+			"instance" : source,
+			"ref" : None,
+			"assoc_name" : None,
+			"assoc_index" : None
+		}]
+		#currents = [source]
+		for (name, index) in traversal_list :
+			nexts = []
+			for current in currents :
+				association = current["instance"].associations[name]
+				if (index >= 0 ) :
+					nexts.append({
+						"instance" : association.instances[index],
+						"ref" : current["instance"],
+						"assoc_name" : name,
+						"assoc_index" : index
+					})
+				elif (index == -1) :
+					for i in association.instances:
+						nexts.append({
+							"instance" : association.instances[i],
+							"ref" : current["instance"],
+							"assoc_name" : name,
+							"assoc_index" : index
+						})
+					#nexts.extend( association.instances.values() )
+				else :
+					raise AssociationReferenceException("Incorrect index in association reference.")
+			currents = nexts
+		return currents
+			
+	@abc.abstractmethod
+	def instantiate(self, class_name, construct_params):
+		pass
+		
+	def createInstance(self, to_class, construct_params = []):
+		instance = self.instantiate(to_class, construct_params)
+		self.instances.add(instance)
+		return instance
+	
+class Event(object):
+	def __init__(self, event_name, port = "", parameters = []):
+		self.name = event_name
+		self.parameters = parameters
+		self.port = port
+
+	def getName(self):
+		return self.name
+
+	def getPort(self):
+		return self.port
+
+	def getParameters(self):
+		return self.parameters
+	
+	def __repr__(self):
+		representation = "(event name : " + str(self.name) + "; port : " + str(self.port)
+		if self.parameters :
+			representation += "; parameters : " + str(self.parameters)
+		representation += ")"
+		return representation
+	
+class OutputListener(object):
+	def __init__(self, port_names):
+		self.port_names = port_names
+		self.queue = Queue()
+
+	def add(self, event):
+		if len(self.port_names) == 0 or event.getPort() in self.port_names :
+			self.queue.put_nowait(event)
+			
+	""" Tries for timeout seconds to fetch an event, returns None if failed.
+		0 as timeout means no waiting (blocking), returns None if queue is empty.
+		-1 as timeout means blocking until an event can be fetched. """
+	def fetch(self, timeout = 0):
+		if timeout < 0:
+			timeout = INFINITY
+		while timeout >= 0:
+			try:
+				# wait in chunks of 100ms because we
+				# can't receive (keyboard)interrupts while waiting
+				return self.queue.get(True, 0.1 if timeout > 0.1 else timeout)
+			except Empty:
+				timeout -= 0.1
+		return None
+
+class InputPortEntry(object):
+	def __init__(self, virtual_name, instance):
+		self.virtual_name = virtual_name
+		self.instance = instance
+		
+class ControllerBase(object):
+
+	def __init__(self, object_manager):
+		self.object_manager = object_manager
+
+		self.private_port_counter = 0
+
+		# Keep track of input ports
+		self.input_ports = {}
+		self.input_queue = EventQueue()
+
+		# Keep track of output ports
+		self.output_ports = []
+		self.output_listeners = []
+
+		# Let statechart run one last time before stopping
+		self.done = False
+			
+	def addInputPort(self, virtual_name, instance = None):
+		if instance == None :
+			port_name = virtual_name
+		else:
+			port_name = "private_" + str(self.private_port_counter) + "_" + virtual_name
+			self.private_port_counter += 1
+		self.input_ports[port_name] = InputPortEntry(virtual_name, instance)
+		return port_name
+		
+	def addOutputPort(self, port_name):
+		self.output_ports.append(port_name)
+
+	def broadcast(self, new_event):
+		self.object_manager.broadcast(new_event)
+		
+	def start(self):
+		self.object_manager.start()
+	
+	def stop(self):
+		pass
+
+	def addInput(self, input_event_list, time_offset = 0.0):
+		if not isinstance(input_event_list, list):
+			input_event_list = [input_event_list]
+
+		for e in input_event_list:
+			if e.getName() == ""  :
+				raise InputException("Input event can't have an empty name.")
+		
+			if e.getPort() not in self.input_ports :
+				raise InputException("Input port mismatch, no such port: " + e.getPort() + ".")	 
+
+		self.input_queue.add(input_event_list, time_offset)
+
+	def getWaitTime(self):
+		return min(self.object_manager.getWaitTime(), self.input_queue.getEarliestTime())
+
+	def handleInput(self, delta):
+		self.input_queue.decreaseTime(delta)
+		for events in self.input_queue.popDueEvents():
+			for e in events:
+				input_port = self.input_ports[e.getPort()]