Просмотр исходного кода

Revert "Merge branch 'testing' into debugging"

This reverts commit a50a088999e55684635b4e498de694e4c3a0945d, reversing
changes made to b541bb495ed8e1b08ce855c28753c56dcf899d75.
Yentl Van Tendeloo 8 лет назад
Родитель
Сommit
6c2b2cb440
100 измененных файлов с 29959 добавлено и 3825 удалено
  1. 36 13
      README.md
  2. 73 55
      bootstrap/bootstrap.py
  3. 129 0
      bootstrap/compilation_manager.alc
  4. 28 107
      bootstrap/conformance_scd.alc
  5. 113 127
      bootstrap/constructors.alc
  6. 0 1867
      bootstrap/core_algorithm.alc
  7. 0 129
      bootstrap/core_formalism.mvc
  8. 10 0
      bootstrap/initial_code_manager.alb
  9. 6 6
      bootstrap/initial_code_manager.alc
  10. 0 21
      bootstrap/initial_code_task.alc
  11. 4 1
      bootstrap/library.alc
  12. 233 162
      bootstrap/metamodels.alt
  13. 0 415
      bootstrap/mini_modify.alc
  14. 95 218
      bootstrap/model_management.alc
  15. 163 177
      bootstrap/modelling.alc
  16. 70 92
      bootstrap/object_operations.alc
  17. 0 53
      bootstrap/pm.mvc
  18. 6 55
      bootstrap/primitives.alc
  19. 106 119
      bootstrap/ramify.alc
  20. 27 0
      bootstrap/task_interface.alc
  21. 12 18
      bootstrap/task_manager.alc
  22. 0 15
      bootstrap/tracability.mvc
  23. 58 175
      bootstrap/transform.alc
  24. 1256 0
      core/core_algorithm.alc
  25. 118 0
      core/core_formalism.mvc
  26. 288 0
      core/mini_modify.alc
  27. 1 0
      core/mini_modify.alh
  28. BIN
      doc/_build/doctrees/actionlanguage.doctree
  29. BIN
      doc/_build/doctrees/advanced.doctree
  30. BIN
      doc/_build/doctrees/communication_models.doctree
  31. BIN
      doc/_build/doctrees/components.doctree
  32. BIN
      doc/_build/doctrees/examples.doctree
  33. BIN
      doc/_build/doctrees/howto.doctree
  34. BIN
      doc/_build/doctrees/index.doctree
  35. BIN
      doc/_build/doctrees/installation.doctree
  36. BIN
      doc/_build/doctrees/interface.doctree
  37. BIN
      doc/_build/doctrees/internal.doctree
  38. BIN
      doc/_build/doctrees/modellanguage.doctree
  39. BIN
      doc/_build/doctrees/models.doctree
  40. BIN
      doc/_build/doctrees/problems.doctree
  41. 4 0
      doc/_build/html/.buildinfo
  42. 5017 0
      doc/_build/html/_images/mvk_server.svg
  43. 1719 0
      doc/_build/html/_images/mvs_server.svg
  44. 425 0
      doc/_build/html/_images/overview.svg
  45. BIN
      doc/_build/html/_images/prompt_fibonacci.png
  46. BIN
      doc/_build/html/_images/prompt_fibonacci_more.png
  47. BIN
      doc/_build/html/_images/prompt_pn_interface.png
  48. 296 0
      doc/_build/html/_sources/actionlanguage.txt
  49. 14 0
      doc/_build/html/_sources/advanced.txt
  50. 42 0
      doc/_build/html/_sources/communication_models.txt
  51. 47 0
      doc/_build/html/_sources/components.txt
  52. 469 0
      doc/_build/html/_sources/examples.txt
  53. 179 0
      doc/_build/html/_sources/howto.txt
  54. 24 0
      doc/_build/html/_sources/index.txt
  55. 72 0
      doc/_build/html/_sources/installation.txt
  56. 98 0
      doc/_build/html/_sources/interface.txt
  57. 218 0
      doc/_build/html/_sources/internal.txt
  58. 174 0
      doc/_build/html/_sources/modellanguage.txt
  59. 20 0
      doc/_build/html/_sources/models.txt
  60. 2 0
      doc/_build/html/_sources/problems.txt
  61. BIN
      doc/_build/html/_static/ajax-loader.gif
  62. 693 0
      doc/_build/html/_static/alabaster.css
  63. 604 0
      doc/_build/html/_static/basic.css
  64. 261 0
      doc/_build/html/_static/classic.css
  65. BIN
      doc/_build/html/_static/comment-bright.png
  66. BIN
      doc/_build/html/_static/comment-close.png
  67. BIN
      doc/_build/html/_static/comment.png
  68. 1 0
      doc/_build/html/_static/custom.css
  69. 287 0
      doc/_build/html/_static/doctools.js
  70. BIN
      doc/_build/html/_static/down-pressed.png
  71. BIN
      doc/_build/html/_static/down.png
  72. BIN
      doc/_build/html/_static/file.png
  73. 10308 0
      doc/_build/html/_static/jquery-1.11.1.js
  74. 4 0
      doc/_build/html/_static/jquery.js
  75. BIN
      doc/_build/html/_static/minus.png
  76. BIN
      doc/_build/html/_static/plus.png
  77. 63 0
      doc/_build/html/_static/pygments.css
  78. 651 0
      doc/_build/html/_static/searchtools.js
  79. 159 0
      doc/_build/html/_static/sidebar.js
  80. 999 0
      doc/_build/html/_static/underscore-1.3.1.js
  81. 31 0
      doc/_build/html/_static/underscore.js
  82. BIN
      doc/_build/html/_static/up-pressed.png
  83. BIN
      doc/_build/html/_static/up.png
  84. 808 0
      doc/_build/html/_static/websupport.js
  85. 436 0
      doc/_build/html/actionlanguage.html
  86. 130 0
      doc/_build/html/advanced.html
  87. 139 0
      doc/_build/html/communication_models.html
  88. 153 0
      doc/_build/html/components.html
  89. 573 0
      doc/_build/html/examples.html
  90. 89 0
      doc/_build/html/genindex.html
  91. 405 0
      doc/_build/html/howto.html
  92. 175 0
      doc/_build/html/index.html
  93. 189 0
      doc/_build/html/installation.html
  94. 267 0
      doc/_build/html/interface.html
  95. 364 0
      doc/_build/html/internal.html
  96. 289 0
      doc/_build/html/modellanguage.html
  97. 120 0
      doc/_build/html/models.html
  98. BIN
      doc/_build/html/objects.inv
  99. 109 0
      doc/_build/html/problems.html
  100. 0 0
      doc/_build/html/search.html

+ 36 - 13
README.md

@@ -10,32 +10,52 @@ Starting up the Modelverse
 ==========================
 
 Starting up the Modelverse is easy: simply execute the `scripts/run_local_modelverse.py` script, with as parameter the port you want to use.
-By default, port 8001 is used.
+This will compile the Modelverse statechart and execute it afterwards.
+You can now directly communicate with the Modelverse task initialisation layer.
+It is not recommended that you do this manually, so we will now introduce the action language.
+
+Compiling Action Language
+=========================
+
+For a more user-friendly experience, an Action Language compiler was introduced that can automatically generate Modelverse instructions.
+During compilation, a live Modelverse is required, as the bytecodes are immediately uploaded after compilation.
+The Modelverse uses a traditional compilation phase and linking phase, though this is all hidden to the user through the `scripts/make_all.py` script.
+The script takes as parameter the address of the Modelverse, the taskname with which to communicate, and a list of source files.
+For realistic applications, we recommend to always link to the bootstrap code, by including the file `bootstrap/\*.alc`.
+Even on systems that don't support globbing (e.g., Windows), this will automatically be expanded by the compiler.
+
+For example, to compile the simple textual interface, you must compile the interface's action language, together with all bootstrapping code (the libraries):
+
+```sh
+python scripts/make_all.py http://127.0.0.1:8001 test_task bootstrap/*.alc integration/code/pn_interface.alc
+```
+
+Compilation is (relatively) smart, as it will not compile code again that is already present in the Modelverse.
+As such, except for the first task, the bootstrap code no longer needs to be compiled, only linked.
+In the future, this is expected to become more user friendly for users, such that they no longer need to have the bootstrapping code available locally.
+
+After this part, your action language in `integration/code/pn_interface.alc` is compiled and running on the Modelverse.
+The Modelverse will, during loading, execute the main function it finds in any of these files.
 
 Communicating with the Modelverse
 =================================
 
-Now that the Modelverse is running, you will want to communicate with it!
+Now that your code is running on the Modelverse, you will want to communicate with it!
 To do this, you can use whatever tool you want, as long as it can send and receive XML/HTTPRequests.
 For example, a mere internet browser can already communicate with the Modelverse, though not in the most user-friendly way.
 
 A nicer way is through the Python prompt script `scripts/prompt.py`.
 After that, it will print out all the output of the Modelverse, and send in all your queries directly to the Modelverse.
 
-Python wrapper
-==============
-
-To automatically communicate with the Modelverse in a programmatic way, a Python wrapper is provided.
-This wrapper is found in `wrappers/modelverse.py`, and provides Python functions that make the necessary Modelverse requests.
-At the moment, not all functions are implemented in the wrapper yet.
-
 Performance
 ===========
 
-Performance of the Modelverse is currently rather low.
-This is primarily caused by the reliance on the action language, which is an explicitly modelled (and interpreted) language.
-Additionally, the Modelverse runs remotely, meaning that all requests have to pass over the network.
-Even when this is executed on the same machine, this causes quite some overhead.
+Performance of the Modelverse is currently rather low, especially in the make\_all script, as this uses an explicitly modelled bytecode upload system.
+To drastically increase performance, this can be switched to a native implementation and a different compiler.
+Additionally, all compilations of source files can happen in parallel, using as many cores as are available.
+Even further, you can skip symbol resolution in the linking phase if you know that all symbols are defined.
+To do all of this, use the `scripts/make_parallel.py` script.
+It is identical to the `scripts/make_all.py` script, but uses multiple cores and uses native code.
 
 Additional documentation
 ========================
@@ -50,6 +70,9 @@ Running the tests is easy: simply execute `scripts/run_tests.py` in the main mod
 This will invoke the necessary build commands (to create bootstrapping code etc.) and call the tests for each individual aspect of the Modelverse.
 Note that testing is done using py.test, which is the only dependency of the Modelverse (and only for tests, of course).
 
+Regarding performance of tests, the tests will try to execute the compilation in parallel, though they test both the explicitly modelled upload system and the native code.
+As such, test performance for the "co\_\*" tests is known to be slow.
+
 Using PyPy
 ----------
 

+ 73 - 55
bootstrap/bootstrap.py

@@ -8,8 +8,9 @@ def bootstrap():
     root = ["__hierarchy"]
 
     task_manager = "task_manager"
-    initial_code_manager = "bootstrap/initial_code_manager.alc"
-    initial_code_task = "bootstrap/initial_code_task.alc"
+    initial_code_manager = "bootstrap/initial_code_manager.alb"
+    initial_code_task = "bootstrap/initial_code_task.alb"
+    bootstrap_files = glob.glob("bootstrap/*.alc") + [initial_code_manager, initial_code_task]
 
     task_data = [   "input",
                     "output",
@@ -18,6 +19,7 @@ def bootstrap():
                     ]
 
     task_frame = [  "evalstack",
+                    "symbols",
                     "returnvalue",
                     ]
 
@@ -66,7 +68,6 @@ def bootstrap():
                     "list_delete": ["Element", "Element", "Integer"],
                     "list_len": ["Integer", "Element"],
                     "dict_add": ["Element", "Element", "Element", "Element"],
-                    "dict_add_fast": ["Element", "Element", "Element", "Element"],
                     "dict_delete": ["Element", "Element", "Element"],
                     "dict_delete_node": ["Element", "Element", "Element"],
                     "dict_read": ["Element", "Element", "Element"],
@@ -102,6 +103,7 @@ def bootstrap():
                     "element_neq": ["Boolean", "Element", "Element"],
                     "read_root": ["Element"],
                     "read_taskroot": ["Element"],
+                    "deserialize": ["Element", "String"],
                     "log": ["String", "String"],
                     "time": ["Float"],
                     "hash": ["String", "String"],
@@ -136,31 +138,40 @@ def bootstrap():
                 # Create all children of the root
                 for node in root:
                     f.write("Node %s()\n" % node)
-                    f.write("Dict (root, \"%s\", %s)\n" % (node, 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))
 
                 def declare_primitive_class(primitive_class_name, primitive_decls):
                     f.write("Node %s()\n" % primitive_class_name)
-                    f.write("Dict (__hierarchy, \"%s\", %s)\n" % (primitive_class_name, primitive_class_name))
+                    f.write("Edge _%s(__hierarchy, %s)\n" % (primitive_class_name, primitive_class_name))
+                    f.write('Node __%s("%s")\n' % (primitive_class_name, primitive_class_name))
+                    f.write("Edge ___%s(_%s, __%s)\n" % (primitive_class_name, primitive_class_name, primitive_class_name))
 
                     # Define all primitive functions
                     for function, parameters in primitive_decls.iteritems():
                         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 _%s_%s(%s, _func_signature_%s)\n" % (primitive_class_name, function, primitive_class_name, function))
+                        f.write('Node _name_%s("%s")\n' % (function, function))
+                        f.write("Edge _%s_name_%s(_%s_%s, _name_%s)\n" % (primitive_class_name, function, primitive_class_name, function, function))
 
-                        f.write('Dict (%s, "%s", _func_signature_%s)\n' % (primitive_class_name, function, function))
-                        f.write('Dict (_func_signature_%s, "body", _func_body_%s)\n' % (function, function))
-                        f.write('Dict (_func_signature_%s, "params", _func_params_%s)\n' % (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))
 
                         parameter_names = "abcdefghijklmnopqrstuvwxyz"
                         for number, param in enumerate(parameters[1:]):
                             param_encoding = "%s_%s" % (function, parameter_names[number])
                             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))
@@ -173,84 +184,91 @@ def bootstrap():
 
                 for data in task_data:
                     f.write("Node task_%s()\n" % data)
-                    f.write('Dict (task_root, "%s", task_%s)\n' % (data, data))
+                    f.write('Node ___task_%s("%s")\n' % (data, data))
+                    f.write("Edge _task_%s(task_root, task_%s)\n" % (data, data))
+                    f.write("Edge __task_%s(_task_%s, ___task_%s)\n" % (data, data, data))
 
                 for data in task_frame:
                     f.write("Node task_%s()\n" % data)
-                    f.write('Dict (task_frame, "%s", task_%s)\n' % (data, data))
+                    f.write('Node ___task_%s("%s")\n' % (data, data))
+                    f.write("Edge _task_%s(task_frame, task_%s)\n" % (data, data))
+                    f.write("Edge __task_%s(_task_%s, ___task_%s)\n" % (data, data, data))
 
                 # Add last_input and last_output links
                 for data in ["input", "output"]:
-                    f.write('Dict (task_root, "last_%s", task_%s)\n' % (data, data))
+                    f.write('Node ___task_last_%s("last_%s")\n' % (data, data))
+                    f.write("Edge _task_last_%s(task_root, task_%s)\n" % (data, data))
+                    f.write("Edge __task_last_%s(_task_last_%s, ___task_last_%s)\n" % (data, data, data))
                     
                 # Bind task to the root
-                f.write('Dict (root, "%s", task_root)\n' % (task_manager))
+                f.write('Node ___new_task("%s")\n' % task_manager)
+                f.write("Edge _new_task(root, task_root)\n")
+                f.write("Edge __new_task(_new_task, ___new_task)\n")
 
-                def compile_code_AL(filename, target, prepend="", main=False):
+                def compile_code_AL(filename, target, prepend="", main=False, symbols=None):
                     import sys
                     sys.path.append("interface/HUTN/")
                     from hutn_compiler.compiler import main as compile_code
-                    code = compile_code(filename, "interface/HUTN/grammars/actionlanguage.g", "BS", ["--debug", "--prepend:%s" % prepend, "--main" if main else "--not-main"])
+                    code = compile_code(filename, "interface/HUTN/grammars/actionlanguage.g", "BS", ["--debug", "--prepend:%s" % prepend, "--main" if main else "--not-main"], symbols=symbols)
                     return code.replace("auto_initial_IP", target)
 
                 # Create all library code
                 # But first create the structure to hold compiled data
                 f.write("Node __objects()\n", both=False)
-                f.write('Dict (__hierarchy, "objects", __objects)\n', both=False)
-
-                def compile_code_MO(filename, model_name):
-                    import sys
-                    sys.path.append("interface/HUTN/")
-                    from hutn_compiler.compiler import main as compile_code
-                    model_code = compile_code(filename, "interface/HUTN/grammars/modelling_bootstrap.g", "MB", ["--modelname:%s" % model_name])
-                    return model_code + "\n"
-
-                # Compile all model definitions to ALC directly
-                total_alc = ""
-                binding_alc = 'Void function initialize_MMs():\n\tinitialize_SCD("models/SimpleClassDiagrams")\n'
-
-                bootstrap_models = sorted(glob.glob("bootstrap/*.mvc"))
-                for bootstrap_model in bootstrap_models:
-                    # Compile the subfile
-                    bootstrap_model = bootstrap_model.replace("\\", "/")
-                    model_name = bootstrap_model.rsplit(".mvc", 1)[0].rsplit("/", 1)[1]
-                    print("[MVC] %s" % model_name)
-                    alc = compile_code_MO(bootstrap_model, model_name)
-                    total_alc += alc
-                    binding_alc += "\tinitialize_%s()\n" % model_name
-
-                # Write out the ALC to a new .metamodels.alc
-                binding_alc += "\treturn!\n"
-                new_metamodels_alc = open("bootstrap/metamodels.alt", 'r').read() + total_alc + binding_alc
-
-                # Now overwrite the .metamodels.alc file
-                with open("bootstrap/.metamodels.alc", "w") as mm:
-                    mm.write(new_metamodels_alc)
+                f.write('Node __objects_name("objects")\n', both=False)
+                f.write("Edge __obj_link(__hierarchy, __objects)\n", both=False)
+                f.write("Edge _name_obj_link(__obj_link, __objects_name)\n", both=False)
 
                 # Compile all files and add to structure manually
-                bootstrap_files = sorted(glob.glob("bootstrap/*.alc") + glob.glob("bootstrap/.*.alc"))
                 for bootstrap_file in bootstrap_files:
                     # Compile the subfile
                     bootstrap_file = bootstrap_file.replace("\\", "/")
-                    print("[ALC] %s" % bootstrap_file)
-                    f.write(compile_code_AL(bootstrap_file, "initial_IP", prepend=bootstrap_file, main = bootstrap_file in [initial_code_manager, initial_code_task]), both=False)
+                    print("[COMP] %s" % bootstrap_file)
+                    symbols = {}
+                    f.write(compile_code_AL(bootstrap_file, "initial_IP", prepend=bootstrap_file, symbols=symbols, main = bootstrap_file in [initial_code_manager, initial_code_task]), both=False)
 
                     # Now link the code with the compilation manager structure
                     f.write("Node elem()\n", both=False)
-
-                    f.write('Dict (__objects, "%s", elem)\n' % bootstrap_file, both=False)
-                    f.write('Dict (elem, "initializers", %s_initial_IP)\n' % bootstrap_file, both=False)
+                    f.write('Node initializers("initializers")\n', both=False)
+                    f.write('Node hash("hash_md5")\n', both=False)
+                    f.write("Edge _(__objects, elem)\n", both=False)
+                    f.write('Node filename("%s")\n' % bootstrap_file, both=False)
+                    f.write("Edge _(_, filename)\n", both=False)
+                    f.write("Edge _(elem, %s_initial_IP)\n" % bootstrap_file, both=False)
+                    f.write("Edge _(_, initializers)\n", both=False)
+                    md5 = hashlib.md5()
+                    md5.update(open(bootstrap_file, 'r').read())
+                    f.write('Node hash_value("%s")\n' % md5.hexdigest(), both=False)
+                    f.write("Edge _(elem, hash_value)\n", both=False)
+                    f.write("Edge _(_, hash)\n", both=False)
+
+                    f.write('Node symbols("symbols")\n', both=False)
+                    f.write('Node __symbols()\n', both=False)
+                    f.write('Edge _(elem, __symbols)\n', both=False)
+                    f.write('Edge _(_, symbols)\n', both=False)
+
+                    for k, v in symbols.items():
+                        f.write('Node v(%s)\n' % v, both=False)
+                        f.write('Node k("%s")\n' % k, both=False)
+                        f.write('Edge _(__symbols, v)\n', both=False)
+                        f.write('Edge _(_, k)\n', both=False)
 
                 # Create code for initial task
                 print("[BOOT] task_manager")
-                f.write('Dict (task_frame, "IP", %s_initial_IP)\n' % (initial_code_manager), both=False)
+                f.write('Node _IP_str("IP")\n', both=False)
+                f.write("Edge _task_frame(task_frame, %s_initial_IP)\n" % initial_code_manager, both=False)
+                f.write("Edge __task_frame(_task_frame, _IP_str)\n", both=False)
 
                 f.write('Node __phase("init")\n', both=False)
-                f.write('Dict (task_frame, "phase", __phase)\n', both=False)
+                f.write('Node __phase_str("phase")\n', both=False)
+                f.write("Edge _task_phase(task_frame, __phase)\n", both=False)
+                f.write("Edge __task_phase(_task_phase, __phase_str)\n", both=False)
 
                 # Create code for new tasks to start at
                 print("[BOOT] new_task")
-                f.write('Dict (__hierarchy, "__IP", %s_initial_IP)\n' % initial_code_task, both=False)
+                f.write('Node __IP_str("__IP")\n', both=False)
+                f.write("Edge _task_IP(__hierarchy, %s_initial_IP)\n" % initial_code_task, both=False)
+                f.write("Edge __task_IP(_task_IP, __IP_str)\n", both=False)
     except:
         os.remove("bootstrap/bootstrap.m.gz")
         os.remove("bootstrap/minimal.m.gz")

+ 129 - 0
bootstrap/compilation_manager.alc

@@ -0,0 +1,129 @@
+include "primitives.alh"
+include "constructors.alh"
+include "conformance_scd.alh"
+
+Void function compilation_manager():
+	String operation
+	String object_name
+	Element root
+	Element mv_root
+	Element node
+
+	mv_root = read_root()
+	root = mv_root["__hierarchy"]["objects"]
+
+	operation = input()
+	if (operation == "upload"):
+		object_name = input()
+		node = create_node()
+		dict_add(node, "hash_md5", input())
+		if (input()):
+			dict_add(node, "initializers", construct_top())
+		else:
+			dict_add(node, "initializers", deserialize(input()))
+
+		Element symbols
+		symbols = create_node()
+		dict_add(node, "symbols", symbols)
+		while (input()):
+			dict_add(symbols, input(), input())
+
+		if (dict_in(root, object_name)):
+			// Already exists, so remove first
+			dict_delete(root, object_name)
+		dict_add(root, object_name, node)
+	elif (operation == "read_initializers"):
+		node = root[input()]["initializers"]
+		output(node)
+	elif (operation == "link_and_load"):
+		Element objs
+		String obj
+
+		objs = create_node()
+		obj = input()
+		while (obj != ""):
+			if (dict_in(root, obj)):
+				set_add(objs, obj)
+			else:
+				log("ERROR: couldn't find obj " + obj)
+			obj = input()
+
+		link_and_load(root, input(), objs)
+	elif (operation == "is_defined"):
+		object_name = input()
+		if (dict_in(root, object_name)):
+			output(root[object_name]["hash_md5"])
+		else:
+			output(create_node())
+	else:
+		log("Failed to understand command")
+
+	return!
+
+String function check_symbols(root : Element, main_function : String, objs : Element):
+	Element symbols
+	String obj
+	Element keys
+	String key
+	Element copy_objs
+
+	// We always need a main variable
+	symbols = create_node()
+	dict_add(symbols, main_function, False)
+
+	// Resolve all symbols
+	copy_objs = set_copy(objs)
+	while (0 < list_len(copy_objs)):
+		obj = set_pop(copy_objs)
+		keys = dict_keys(root[obj]["symbols"])
+		while (0 < list_len(keys)):
+			key = set_pop(keys)
+
+			if (root[obj]["symbols"][key]):
+				// Defines
+				if (bool_not(dict_in(symbols, key))):
+					// Not yet in dictionary
+					dict_add(symbols, key, True)
+				elif (symbols[key]):
+					// Already in dictionary, and it was already defined
+					return "ERROR: multiple definition of symbol " + key!
+				else:
+					// Already in dictionary, but only used
+					dict_delete(symbols, key)
+					dict_add(symbols, key, True)
+			else:
+				// Uses
+				if (bool_not(dict_in(symbols, key))):
+					dict_add(symbols, key, False)
+
+	// Check whether we have everything
+	keys = dict_keys(symbols)
+	while (0 < list_len(keys)):
+		key = set_pop(keys)
+		if (bool_not(symbols[key])):
+			if (bool_not(bool_or(key == "output", key == "input"))):
+				return "ERROR: undefined symbol " + key!
+
+	return "OK"!
+
+Void function link_and_load(root : Element, main_function : String, objs : Element):
+	String obj
+	Element func
+	Element main_f
+	String result
+
+	result = check_symbols(root, main_function, objs)
+	output(result)
+
+	if (result == "OK"):
+		// Symbols verified OK, start execution
+		// Call all initializers in turn
+		while (0 < list_len(objs)):
+			obj = set_pop(objs)
+			func = root[obj]["initializers"]
+			exec(func)
+
+		// Resolve the main function, which should now be in (global) scope, and execute it
+		main_f = resolve(main_function)
+		main_f()
+	return!

+ 28 - 107
bootstrap/conformance_scd.alc

@@ -21,9 +21,6 @@ Boolean function is_nominal_instance(model : Element, instance : String, type :
 		// doesn't even have a type
 		return False!
 
-	if (value_eq(model["type_mapping"][instance], type)):
-		return True!
-
 	return is_nominal_subtype(model["metamodel"], model["type_mapping"][instance], type)!
 
 Boolean function is_nominal_subtype(metamodel : Element, subclass : String, superclass : String):
@@ -48,7 +45,6 @@ Element function precompute_cardinalities(model : Element):
 	Element cardinalities
 	Element keys
 	Element metamodel
-	Boolean optional
 
 	metamodel = model["metamodel"]
 	keys = allInstances(metamodel, "Association")
@@ -63,34 +59,16 @@ Element function precompute_cardinalities(model : Element):
 		tuc = read_attribute(metamodel, key, "target_upper_cardinality")
 
 		if (element_neq(slc, read_root())):
-			dict_add_fast(tmp_dict, "slc", slc)
+			dict_add(tmp_dict, "slc", slc)
 		if (element_neq(suc, read_root())):
-			dict_add_fast(tmp_dict, "suc", suc)
+			dict_add(tmp_dict, "suc", suc)
 		if (element_neq(tlc, read_root())):
-			dict_add_fast(tmp_dict, "tlc", tlc)
+			dict_add(tmp_dict, "tlc", tlc)
 		if (element_neq(tuc, read_root())):
-			dict_add_fast(tmp_dict, "tuc", tuc)
-
-		if (list_len(tmp_dict) > 0):
-			dict_add_fast(cardinalities, key, tmp_dict)
-
-	keys = allInstances(metamodel, "AttributeLink")
-	while (0 < list_len(keys)):
-		key = set_pop(keys)
-		tmp_dict = create_node()
-
-		// Attributes always have 1 max
-		dict_add_fast(tmp_dict, "tuc", 1)
-
-		// Depending on whether it is optional or not, the cardinality is changed
-		optional = read_attribute(metamodel, key, "optional")
-		if (optional):
-			dict_add_fast(tmp_dict, "tlc", 0)
-		else:
-			dict_add_fast(tmp_dict, "tlc", 1)
+			dict_add(tmp_dict, "tuc", tuc)
 
 		if (list_len(tmp_dict) > 0):
-			dict_add_fast(cardinalities, key, tmp_dict)
+			dict_add(cardinalities, key, tmp_dict)
 
 	return cardinalities!
 
@@ -115,11 +93,6 @@ String function conformance_scd(model : Element):
 	Element spi_cache
 	Element constraint_function
 
-	Element reverse_m
-	Element reverse_mm
-	reverse_m = make_reverse_dictionary(model["model"])
-	reverse_mm = make_reverse_dictionary(model["metamodel"]["model"])
-
 	spo_cache = create_node()
 	spi_cache = create_node()
 
@@ -149,20 +122,16 @@ String function conformance_scd(model : Element):
 				return "Type of element not in specified metamodel: " + model_info(model, model_name)!
 
 			if (is_edge(element)):
-				src_model = reverse_m[cast_id2s(read_edge_src(element))]
-				dst_model = reverse_m[cast_id2s(read_edge_dst(element))]
-				src_metamodel = reverse_mm[cast_id2s(read_edge_src(metamodel["model"][typing[model_name]]))]
-				dst_metamodel = reverse_mm[cast_id2s(read_edge_dst(metamodel["model"][typing[model_name]]))]
+				src_model = reverseKeyLookup(model["model"], read_edge_src(element))
+				dst_model = reverseKeyLookup(model["model"], read_edge_dst(element))
+				src_metamodel = reverseKeyLookup(metamodel["model"], read_edge_src(metamodel["model"][typing[model_name]]))
+				dst_metamodel = reverseKeyLookup(metamodel["model"], read_edge_dst(metamodel["model"][typing[model_name]]))
 
 				if (bool_not(is_nominal_instance(model, src_model, src_metamodel))):
-					log("got: " + src_model)
-					log("expected: " + src_metamodel)
 					return "Source of model edge not typed by source of type: " + model_info(model, model_name)!
 
 				if (bool_not(is_nominal_instance(model, dst_model, dst_metamodel))):
-					log("got: " + dst_model)
-					log("expected: " + dst_metamodel)
-					return "Destination of model edge not typed by destination of type: " + model_info(model, model_name)!
+					return "Destination of model edge not typed by source of type: " + model_info(model, model_name)!
 
 			// Check cardinality for all of our edges
 			//
@@ -171,7 +140,7 @@ String function conformance_scd(model : Element):
 			//
 			// First the incoming, so we are at B in the above figure
 			if (bool_not(dict_in(spo_cache, type_name))):
-				dict_add_fast(spo_cache, type_name, selectPossibleOutgoing(metamodel, type_name, dict_keys(cardinalities)))
+				dict_add(spo_cache, type_name, selectPossibleOutgoing(metamodel, type_name, dict_keys(cardinalities)))
 
 			check_list = set_copy(spo_cache[type_name])
 			while (0 < list_len(check_list)):
@@ -195,7 +164,7 @@ String function conformance_scd(model : Element):
 
 			// Identical, but for outgoing, and thus for A in the figure
 			if (bool_not(dict_in(spi_cache, type_name))):
-				dict_add_fast(spi_cache, type_name, selectPossibleIncoming(metamodel, type_name, dict_keys(cardinalities)))
+				dict_add(spi_cache, type_name, selectPossibleIncoming(metamodel, type_name, dict_keys(cardinalities)))
 
 			check_list = set_copy(spi_cache[type_name])
 			while (0 < list_len(check_list)):
@@ -220,23 +189,17 @@ String function conformance_scd(model : Element):
 			constraint_function = read_attribute(metamodel, typing[model_name], "constraint")
 			if (element_neq(constraint_function, read_root())):
 				String result
-				Element func
-
-				func = get_func_AL_model(import_node(constraint_function))
-				result = func(model, model_name)
-
+				result = constraint_function(model, model_name)
 				if (result != "OK"):
 					return result!
 
 	// Check multiplicities, if they are defined (optional)
 	Element metamodel_keys
 	String metamodel_element
-	Element mm_model
 	Integer attr_value
-	mm_model = metamodel["model"]
 
-	metamodel_keys = dict_keys(mm_model)
-	while (read_nr_out(metamodel_keys) > 0):
+	metamodel_keys = dict_keys(metamodel["model"])
+	while (0 < list_len(metamodel_keys)):
 		metamodel_element = set_pop(metamodel_keys)
 
 		// Lower multiplicities
@@ -253,58 +216,18 @@ String function conformance_scd(model : Element):
 			if (attr_value < list_len(allInstances(model, metamodel_element))):
 				return "Upper cardinality violated for class: " + metamodel_element!
 
-	// Check all ComplexAttributes recursively
-	Element all_complex_types
-	Element complex_instances
-	String complex_instance
-	String complex_type
-	String result
-	all_complex_types = allInstances(model["metamodel"]["metamodel"], "ComplexAttribute")
-	while (read_nr_out(all_complex_types) > 0):
-		complex_type = set_pop(all_complex_types)
-		complex_instances = allInstances(model, complex_type)
-
-		while (read_nr_out(complex_instances) > 0):
-			complex_instance = set_pop(complex_instances)
-
-			complex_type = read_attribute(model["metamodel"], read_type(model, complex_instance), "type")
-			result = check_location_conformance(model["model"][complex_instance], complex_type)
-
-			if (result != "OK"):
-				return ((("Complex attribute doesn't match for: " + complex_instance) + "\n Message: ") + result)!
-
-	// Structure seems fine, now do global constraints
-	Element global_constraints
-	String constraint
-	Element func
-
-	global_constraints = allInstances(model, "GlobalConstraint")
-	while (read_nr_out(global_constraints) > 0):
-		constraint = set_pop(global_constraints)
-		func = get_func_AL_model(import_node(read_attribute(model, constraint, "global_constraint")))
-		result = func(model)
-		if (result != "OK"):
-			return result!
-
-	return "OK"!
-
-String function check_location_conformance(instance_location : String, type_location : String):
-	// Check whether the instance is typed by the type
-	Element instance
-	Element type
-
-	instance = import_node(instance_location)
-	type = import_node(type_location)
-
-	if (element_neq(instance["metamodel"], type)):
-		return "Instance not statically typed by specified metamodel"!
-	
-	return conformance_scd(instance)!
+	// Structure seems fine, now do static semantics
+	if (dict_in(metamodel, "constraints")):
+		Element constraint_function
+		constraint_function = metamodel["constraints"]
+		return constraint_function(model)!
+	else:
+		return "OK"!
 
 Element function set_model_constraints(model : Element, func : Element):
 	if (dict_in(model, "constraints")):
 		dict_delete(model, "constraints")
-	dict_add_fast(model, "constraints", func)
+	dict_add(model, "constraints", func)
 	return model!
 
 Element function generate_bottom_type_mapping(model : Element):
@@ -313,20 +236,18 @@ Element function generate_bottom_type_mapping(model : Element):
 	dict_delete(model, "type_mapping")
 	Element tm
 	tm = create_node()
-	dict_add_fast(model, "type_mapping", tm)
+	dict_add(model, "type_mapping", tm)
 	
 	// Iterate over every element
 	Element elem_keys
-	String elem
-
+	Element elem
 	elem_keys = dict_keys(model["model"])
-	while (read_nr_out(elem_keys) > 0):
+	while (0 < read_nr_out(elem_keys)):
 		elem = set_pop(elem_keys)
-
 		if (is_edge(model["model"][elem])):
-			dict_add_fast(tm, elem, "Edge")
+			dict_add(tm, elem, "Edge")
 		else:
-			dict_add_fast(tm, elem, "Node")
+			dict_add(tm, elem, "Node")
 
 	return model!
 

+ 113 - 127
bootstrap/constructors.alc

@@ -7,67 +7,18 @@ include "modelling.alh"
 Element while_stack = ?
 Element variable_map = ?
 
-Element function construct_function():
+Action function construct_top():
 	String command
-	Element result
-	Element main_function
-	Boolean continue
-	Element prev_element
-	Element first_element
-
-	// Initialize variables
-	prev_element = read_root()
-	main_function = read_root()
-
-	// Clear global variables
-	while_stack = create_node()
-	variable_map = create_node()
-
-	continue = True
-	while (continue):
+	while (True):
 		command = input()
 		if (command == "global"):
-			result = construct_global()
+			return construct_global()!
 		elif (command == "funcdef"):
-			result = construct_funcdef(False)
+			return construct_top_funcdef(False)!
 		elif (command == "mutable_funcdef"):
-			result = construct_funcdef(True)
+			return construct_top_funcdef(True)!
 		else:
 			log("ERROR (1): did not understand command " + cast_e2s(command))
-			output("ERROR: compiled code not understood: " + cast_e2s(command))
-			return read_root()!
-
-		continue = input()
-		if (prev_element != read_root()):
-			dict_add_fast(prev_element, "next", result["start"])
-		else:
-			first_element = result["start"]
-
-		if (bool_and(element_eq(main_function, read_root()), command != "global")):
-			// In case no main function is defined, it is the first defined function
-			// This is mostly there to ensure backwards compatibility
-			main_function = result["instruction"]
-
-		prev_element = result["end"]
-
-		if (value_eq(result["name"], "main")):
-			// It was the function that we want to call
-			main_function = result["instruction"]
-
-	if (element_eq(main_function, read_root())):
-		log("ERROR (2): no main function found")
-		output("ERROR: no main function found")
-		return read_root()!
-
-	// Overwrite the main function with our declaration function
-	prev_element = main_function["body"]
-	log("Got main function V: " + cast_e2s(main_function))
-	log("Got main function S: " + dict_to_string(main_function))
-	dict_delete(main_function, "body")
-	dict_add_fast(main_function, "body", first_element)
-	dict_add_fast(result["end"], "next", prev_element)
-	
-	return main_function!
 
 Action function construct_global():
 	Action this_element
@@ -76,54 +27,50 @@ Action function construct_global():
 
 	this_element = create_value(!global)
 	declared_element = input()
-	dict_add_fast(this_element, "var", declared_element)
+	dict_add(this_element, "var", declared_element)
 
 	// Defines
 	Action assign
 	Action resolve
 	Action value
 	assign = create_value(!assign)
-	dict_add_fast(this_element, "next", assign)
+	dict_add(this_element, "next", assign)
 	resolve = create_value(!resolve)
-	dict_add_fast(assign, "var", resolve)
-	dict_add_fast(resolve, "var", declared_element)
+	dict_add(assign, "var", resolve)
+	dict_add(resolve, "var", declared_element)
 	op = input()
 	if (op == "deref"):
 		value = create_value(!constant)
-		dict_add_fast(value, "node", import_node(input()))
+		dict_add(value, "node", import_node(input()))
 	elif (op == "empty"):
 		value = create_value(!call)
 		Element res
 		Element acc
 		res = create_value(!resolve)
 		acc = create_value(!access)
-		dict_add_fast(value, "func", acc)
-		dict_add_fast(acc, "var", res)
-		dict_add_fast(res, "var", "create_node")
+		dict_add(value, "func", acc)
+		dict_add(acc, "var", res)
+		dict_add(res, "var", "create_node")
 	elif (op == "const"):
 		value = create_value(!constant)
-		dict_add_fast(value, "node", input())
-	dict_add_fast(assign, "value", value)
-
-	Element result
-	result = create_node()
-	dict_add_fast(result, "name", "")
-	dict_add_fast(result, "instruction", this_element)
-	dict_add_fast(result, "start", this_element)
-	dict_add_fast(result, "end", assign)
-	return result!
-
-Action function construct_funcdef(mutable : Boolean):
+		dict_add(value, "node", input())
+	dict_add(assign, "value", value)
+
+	if (input()):
+		dict_add(assign, "next", construct_top())
+	return this_element!
+
+Action function construct_top_funcdef(mutable : Boolean):
 	Action assign
 	Action resolve
 	Action constant
 	Element formal
 	Element func
 	Element params
-	Action declare
+	Action global
 	String name
 
-	declare = create_value(!global)
+	global = create_value(!global)
 	assign = create_value(!assign)
 	resolve = create_value(!resolve)
 	constant = create_value(!constant)
@@ -134,16 +81,16 @@ Action function construct_funcdef(mutable : Boolean):
 		formal = name
 	func = create_node()
 	params = create_node()
-	dict_add_fast(declare, "var", formal)
-	dict_add_fast(declare, "next", assign)
-	dict_add_fast(assign, "var", resolve)
-	dict_add_fast(assign, "value", constant)
-	dict_add_fast(resolve, "var", formal)
-	dict_add_fast(constant, "node", func)
-	dict_add_fast(func, "params", params)
+	dict_add(global, "var", formal)
+	dict_add(global, "next", assign)
+	dict_add(assign, "var", resolve)
+	dict_add(assign, "value", constant)
+	dict_add(resolve, "var", formal)
+	dict_add(constant, "node", func)
+	dict_add(func, "params", params)
 
 	if (mutable):
-		dict_add_fast(func, "mutable", create_node())
+		dict_add(func, "mutable", create_node())
 
 	Integer nrParams
 	nrParams = input()
@@ -156,24 +103,21 @@ Action function construct_funcdef(mutable : Boolean):
 
 	while (counter < nrParams):
 		param = create_node()
-		dict_add_fast(params, string_get(arg_names_decl, counter), param)
-		dict_add_fast(param, "name", string_get(arg_names_decl, counter))
-		dict_add_fast(variable_map, input(), param)
+		dict_add(params, string_get(arg_names_decl, counter), param)
+		dict_add(param, "name", string_get(arg_names_decl, counter))
+		dict_add(variable_map, input(), param)
 		// Output each parameter in turn
 		counter = counter + 1
 
 	// Now add the body
-	dict_add_fast(func, "body", construct_unknown())
+	dict_add(func, "body", construct_unknown())
+
+	if (input()):
+		dict_add(assign, "next", construct_top())
 
-	Element result
-	result = create_node()
-	dict_add_fast(result, "name", name)
-	dict_add_fast(result, "instruction", func)
-	dict_add_fast(result, "start", declare)
-	dict_add_fast(result, "end", assign)
-	return result!
+	return global!
 
-Element function construct_unknown():
+Action function construct_unknown():
 	String elem
 	Element new_model
 	Element new_model_model
@@ -212,37 +156,35 @@ Element function construct_unknown():
 		return construct_unknown()!
 	else:
 		log("ERROR (2): did not understand command " + cast_e2s(elem))
-		output("ERROR: compiled code not understood: " + cast_e2s(elem))
-		return read_root()!
 
 Action function construct_if():
 	Action this_element
 	this_element = create_value(!if)
-	dict_add_fast(this_element, "cond", construct_unknown())
-	dict_add_fast(this_element, "then", construct_unknown())
+	dict_add(this_element, "cond", construct_unknown())
+	dict_add(this_element, "then", construct_unknown())
 	if (input()):
-		dict_add_fast(this_element, "else", construct_unknown())
+		dict_add(this_element, "else", construct_unknown())
 	if (input()):
-		dict_add_fast(this_element, "next", construct_unknown())
+		dict_add(this_element, "next", construct_unknown())
 	return this_element!
 
 Action function construct_while():
 	Action this_element
 	this_element = create_value(!while)
-	dict_add_fast(this_element, "cond", construct_unknown())
+	dict_add(this_element, "cond", construct_unknown())
 
 	list_append(while_stack, this_element)
-	dict_add_fast(this_element, "body", construct_unknown())
+	dict_add(this_element, "body", construct_unknown())
 	list_delete(while_stack, list_len(while_stack) - 1)
 
 	if (input()):
-		dict_add_fast(this_element, "next", construct_unknown())
+		dict_add(this_element, "next", construct_unknown())
 	return this_element!
 
 Action function construct_access():
 	Action this_element
 	this_element = create_value(!access)
-	dict_add_fast(this_element, "var", construct_unknown())
+	dict_add(this_element, "var", construct_unknown())
 	return this_element!
 
 Action function construct_resolve():
@@ -256,22 +198,22 @@ Action function construct_resolve():
 		linked_element = variable_map[name]
 	else:
 		linked_element = name
-	dict_add_fast(this_element, "var", linked_element)
+	dict_add(this_element, "var", linked_element)
 	return this_element!
 
 Action function construct_assign():
 	Action this_element
 	this_element = create_value(!assign)
-	dict_add_fast(this_element, "var", construct_unknown())
-	dict_add_fast(this_element, "value", construct_unknown())
+	dict_add(this_element, "var", construct_unknown())
+	dict_add(this_element, "value", construct_unknown())
 	if (input()):
-		dict_add_fast(this_element, "next", construct_unknown())
+		dict_add(this_element, "next", construct_unknown())
 	return this_element!
 
 Action function construct_call():
 	Action this_element
 	this_element = create_value(!call)
-	dict_add_fast(this_element, "func", construct_unknown())
+	dict_add(this_element, "func", construct_unknown())
 
 	Integer nrParams
 	nrParams = input()
@@ -286,29 +228,29 @@ Action function construct_call():
 	while (counter < nrParams):
 		param = create_node()
 
-		dict_add_fast(param, "name", string_get(arg_names_call, counter))
-		dict_add_fast(param, "value", construct_unknown())
+		dict_add(param, "name", string_get(arg_names_call, counter))
+		dict_add(param, "value", construct_unknown())
 
 		if (counter == 0):
-			dict_add_fast(this_element, "params", param)
+			dict_add(this_element, "params", param)
 		else:
-			dict_add_fast(prev_param, "next_param", param)
+			dict_add(prev_param, "next_param", param)
 		prev_param = param
 
 		counter = counter + 1
 
 	if (nrParams > 0):
-		dict_add_fast(this_element, "last_param", prev_param)
+		dict_add(this_element, "last_param", prev_param)
 
 	if (input()):
-		dict_add_fast(this_element, "next", construct_unknown())
+		dict_add(this_element, "next", construct_unknown())
 	return this_element!
 
 Action function construct_return():
 	if (input()):
 		Action this_element
 		this_element = create_value(!return)
-		dict_add_fast(this_element, "value", construct_unknown())
+		dict_add(this_element, "value", construct_unknown())
 		return this_element!
 	else:
 		return create_value(!return)!
@@ -316,7 +258,7 @@ Action function construct_return():
 Action function construct_const():
 	Action this_element
 	this_element = create_value(!constant)
-	dict_add_fast(this_element, "node", input())
+	dict_add(this_element, "node", input())
 	return this_element!
 
 Action function construct_declare():
@@ -326,11 +268,11 @@ Action function construct_declare():
 
 	this_element = create_value(!declare)
 	declared_element = create_node()
-	dict_add_fast(this_element, "var", declared_element)
+	dict_add(this_element, "var", declared_element)
 	name = input()
-	dict_add_fast(variable_map, name, declared_element)
+	dict_add(variable_map, name, declared_element)
 	if (input()):
-		dict_add_fast(this_element, "next", construct_unknown())
+		dict_add(this_element, "next", construct_unknown())
 	return this_element!
 
 Action function construct_input():
@@ -341,25 +283,69 @@ Action function construct_input():
 Action function construct_output():
 	Action this_element
 	this_element = create_value(!output)
-	dict_add_fast(this_element, "value", construct_unknown())
+	dict_add(this_element, "value", construct_unknown())
 	if (input()):
-		dict_add_fast(this_element, "next", construct_unknown())
+		dict_add(this_element, "next", construct_unknown())
 	return this_element!
 
 Action function construct_deref():
 	Action this_element
 	this_element = create_value(!constant)
-	dict_add_fast(this_element, "node", import_node(input()))
+	dict_add(this_element, "node", import_node(input()))
 	return this_element!
 
 Action function construct_break():
 	Action this_element
 	this_element = create_value(!break)
-	dict_add_fast(this_element, "while", while_stack[list_len(while_stack) - 1])
+	dict_add(this_element, "while", while_stack[list_len(while_stack) - 1])
 	return this_element!
 
 Action function construct_continue():
 	Action this_element
 	this_element = create_value(!continue)
-	dict_add_fast(this_element, "while", while_stack[list_len(while_stack) - 1])
+	dict_add(this_element, "while", while_stack[list_len(while_stack) - 1])
 	return this_element!
+
+Action function construct_function():
+	Action func
+	Integer nrParams
+	Integer counter
+	Element param
+	Element params
+	String arg_names_decl
+	String inp
+
+	variable_map = create_node()
+
+	inp = input()
+	while (bool_and(inp != "funcdef", inp != "mutable_funcdef")):
+		// We skip over everything that is not a funcdef, as these are all just definitions of global stuff
+		inp = input()
+
+	// Consume the name
+	input()
+
+	params = create_node()
+	nrParams = input()
+	counter = 0
+	func = create_node()
+	arg_names_decl = "abcdefghijklmnopqrstuvwxyz"
+	dict_add(func, "params", params)
+
+	if (inp == "mutable_funcdef"):
+		dict_add(func, "mutable", create_node())
+
+	while (counter < nrParams):
+		param = create_node()
+		dict_add(params, string_get(arg_names_decl, counter), param)
+		dict_add(variable_map, input(), param)
+		// Output each parameter in turn
+		counter = counter + 1
+
+	// Now add the body
+	dict_add(func, "body", construct_unknown())
+
+	// Consume the final 'false', to indicate that no additional code will come
+	input()
+
+	return func!

Разница между файлами не показана из-за своего большого размера
+ 0 - 1867
bootstrap/core_algorithm.alc


+ 0 - 129
bootstrap/core_formalism.mvc

@@ -1,129 +0,0 @@
-import models/SimpleClassDiagrams as SimpleClassDiagrams
-include "primitives.alh"
-
-SimpleClassDiagrams CoreFormalism {
-    SimpleAttribute String {
-        constraint = $
-            String function constraint(model : Element, name : String):
-                if (bool_not(is_physical_string(model["model"][name]))):
-                    return "String has no string value"!
-                else:
-                    return "OK"!
-            $
-    }
-
-    SimpleAttribute Permissions {
-        constraint = $
-            String function constraint(model : Element, name : String):
-                Element self
-                self = model["model"][name]
-                if (bool_not(is_physical_string(self))):
-                    return "Permissions has no string value"!
-                if (bool_not(string_len(self) == 3)):
-                    return "Permissions string is not of correct length"!
-                if (bool_or(cast_s2i(string_get(self, 0)) < 0, cast_s2i(string_get(self, 0)) > 2)):
-                    return "Owner permission is not in range [0, 2]"!
-                if (bool_or(cast_s2i(string_get(self, 1)) < 0, cast_s2i(string_get(self, 1)) > 2)):
-                    return "Group permission is not in range [0, 2]"!
-                if (bool_or(cast_s2i(string_get(self, 2)) < 0, cast_s2i(string_get(self, 2)) > 2)):
-                    return "Other permission is not in range [0, 2]"!
-                return "OK"!
-            $
-    }
-
-    SimpleAttribute Boolean {
-        constraint = $
-            String function constraint(model : Element, name : String):
-                if (bool_not(is_physical_boolean(model["model"][name]))):
-                    return "Boolean has no bool value"!
-                else:
-                    return "OK"!
-            $
-    }
-
-    SimpleAttribute Natural {
-        constraint = $
-            String function constraint(model : Element, name : String):
-                if (bool_not(is_physical_int(model["model"][name]))):
-                    return "Natural has no integer value"!
-                elif (integer_lt(model["model"][name], 0)):
-                    return "Natural has negative value"!
-                else:
-                    return "OK"!
-            $
-    }
-
-    SimpleAttribute TypeMapping {
-        constraint = $
-            String function constraint(model : Element, name : String):
-                Element self
-                self = model["model"][name]
-                if (has_value(self)):
-                    return "TypeMapping cannot have a value for root node!"!
-                Element keys
-                String key
-                keys = dict_keys(self)
-                while (read_nr_out(keys) > 0):
-                    key = set_pop(keys)
-                    if (bool_not(is_physical_string(key))):
-                        return ("Key on type mapping is not a string: " + cast_e2s(key))!
-                    elif (bool_not(is_physical_string(self[key]))):
-                        return ("Value on type mapping is not a string for key " + cast_e2s(key))!
-                return "OK"!
-            $
-    }
-
-    Class User {
-        name : String
-        password : String
-        admin : Boolean
-    }
-
-    Class Group {
-        name : String
-    }
-
-    Association ownedBy (Group, User) {}
-    Association belongsTo (User, Group) {}
-
-    Class Model {
-        name : String
-        location : String
-        permissions : Permissions
-    }
-
-    Association instanceOf (Model, Model) {
-        type_mapping : TypeMapping
-    }
-
-    Association owner (Model, User) {
-        target_lower_cardinality = 1
-        target_upper_cardinality = 1
-    }
-
-    Association group (Model, Group) {
-        target_lower_cardinality = 1
-        target_upper_cardinality = 1
-    }
-
-    Class Transformation : Model {}
-
-    Class ModelTransformation : Transformation {}
-
-    Class ActionLanguage : Transformation {}
-
-    Class ExternalTool : Transformation {}
-
-    Class ManualOperation : Transformation {}
-
-    Association transformInput (Model, Transformation) {
-    }
-    Association transformOutput (Transformation, Model) {
-    }
-
-    Association tracability (Model, Model) {
-        type : String
-    }
-}
-
-export CoreFormalism to models/CoreFormalism

+ 10 - 0
bootstrap/initial_code_manager.alb

@@ -0,0 +1,10 @@
+include "bootstrap/primitives.alc"
+include "task_manager.alh"
+
+Void function __main():
+	Element root
+	root = read_root()
+	root = root["__hierarchy"]["objects"]
+	exec(root["bootstrap/task_manager.alc"]["initializers"])
+	task_management()
+	return!

+ 6 - 6
bootstrap/initial_code_manager.alc

@@ -1,17 +1,17 @@
 include "bootstrap/primitives.alc"
-include "task_manager.alh"
+include "task_interface.alh"
 
-Void function __main():
+Void mutable function __main():
 	Element root
 	root = read_root()
 	root = root["__hierarchy"]["objects"]
+	exec(root["bootstrap/compilation_manager.alc"]["initializers"])
 	exec(root["bootstrap/constructors.alc"]["initializers"])
 	exec(root["bootstrap/library.alc"]["initializers"])
 	exec(root["bootstrap/object_operations.alc"]["initializers"])
 	exec(root["bootstrap/conformance_scd.alc"]["initializers"])
-	exec(root["bootstrap/.metamodels.alc"]["initializers"])
+	exec(root["bootstrap/metamodels.alc"]["initializers"])
 	exec(root["bootstrap/modelling.alc"]["initializers"])
-	exec(root["bootstrap/task_manager.alc"]["initializers"])
-	exec(root["bootstrap/core_algorithm.alc"]["initializers"])
-	task_management()
+	exec(root["bootstrap/task_interface.alc"]["initializers"])
+	new_task()
 	return!

+ 0 - 21
bootstrap/initial_code_task.alc

@@ -1,21 +0,0 @@
-include "bootstrap/primitives.alc"
-include "bootstrap/core_algorithm.alc"
-
-Void mutable function __main():
-	Element root
-	root = read_root()
-	root = root["__hierarchy"]["objects"]
-	exec(root["bootstrap/.metamodels.alc"]["initializers"])
-	exec(root["bootstrap/mini_modify.alc"]["initializers"])
-	exec(root["bootstrap/core_algorithm.alc"]["initializers"])
-	exec(root["bootstrap/modelling.alc"]["initializers"])
-	exec(root["bootstrap/library.alc"]["initializers"])
-	exec(root["bootstrap/constructors.alc"]["initializers"])
-	exec(root["bootstrap/object_operations.alc"]["initializers"])
-	exec(root["bootstrap/model_management.alc"]["initializers"])
-	exec(root["bootstrap/ramify.alc"]["initializers"])
-	exec(root["bootstrap/transform.alc"]["initializers"])
-	exec(root["bootstrap/conformance_scd.alc"]["initializers"])
-	exec(root["bootstrap/random.alc"]["initializers"])
-	new_task()
-	return!

+ 4 - 1
bootstrap/library.alc

@@ -20,7 +20,10 @@ Element function export_node(model_name : String, model_reference : Element):
 		counter_i = counter_i + 1
 	
 	// current now contains the place where we should add the element
-	dict_overwrite(current, splitted[length], model_reference)
+	if (bool_not(dict_in(current, splitted[length]))):
+		dict_add(current, splitted[length], model_reference)
+	else:
+		log("Could not export to that location: already in use!")
 
 	return model_reference!
 

+ 233 - 162
bootstrap/metamodels.alt

@@ -4,141 +4,225 @@ include "library.alh"
 include "conformance_scd.alh"
 include "modelling.alh"
 
-String function constraint_Natural(model : Element, name : String):
-	Element self
-	self = model["model"][name]
-	if (is_physical_int(self)):
-		if (integer_gte(self, 0)):
+Element function constraint_natural(model : Element, name : String):
+	if (is_physical_int(model["model"][name])):
+		if (integer_gte(model["model"][name], 0)):
 			return "OK"!
 		else:
 			return "Natural number not larger than or equal to zero"!
 	else:
-		return "Natural number not larger than or equal to zero"!
+		return "Natural has non-integer instance"!
 
-Element function constraint_String(model : Element, name : String):
-	Element self
-	self = model["model"][name]
-	if (is_physical_string(self)):
+Element function constraint_string(model : Element, name : String):
+	if (is_physical_string(model["model"][name])):
 		return "OK"!
 	else:
 		return "String has non-string instance"!
 
-Element function constraint_Boolean(model : Element, name : String):
-	Element self
-	self = model["model"][name]
-	if (is_physical_boolean(self)):
-		return "OK"!
+Element function constraint_if(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "if"):
+			return "OK"!
+		else:
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+	else:
+		return "Expected physical action value"!
+
+Element function constraint_while(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "while"):
+			return "OK"!
+		else:
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+	else:
+		return "Expected physical action value"!
+
+Element function constraint_break(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "break"):
+			return "OK"!
+		else:
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+	else:
+		return "Expected physical action value"!
+
+Element function constraint_continue(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "continue"):
+			return "OK"!
+		else:
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+	else:
+		return "Expected physical action value"!
+
+Element function constraint_assign(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "assign"):
+			return "OK"!
+		else:
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+	else:
+		return "Expected physical action value"!
+
+Element function constraint_return(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "return"):
+			return "OK"!
+		else:
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+	else:
+		return "Expected physical action value"!
+
+Element function constraint_output(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "output"):
+			return "OK"!
+		else:
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+	else:
+		return "Expected physical action value"!
+
+Element function constraint_input(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "input"):
+			return "OK"!
+		else:
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+	else:
+		return "Expected physical action value"!
+
+Element function constraint_declare(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "declare"):
+			return "OK"!
+		else:
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+	else:
+		return "Expected physical action value"!
+
+Element function constraint_global(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "global"):
+			return "OK"!
+		else:
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+	else:
+		return "Expected physical action value"!
+
+Element function constraint_access(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "access"):
+			return "OK"!
+		else:
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
+	else:
+		return "Expected physical action value"!
+
+Element function constraint_constant(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "constant"):
+			return "OK"!
+		else:
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
 	else:
-		return "Boolean has non-boolean instance"!
+		return "Expected physical action value"!
 
-Element function constraint_Location(model : Element, name : String):
-	Element self
-	self = model["model"][name]
-	if (is_physical_string(self)):
-		if (element_neq(import_node(self), read_root())):
+Element function constraint_resolve(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "resolve"):
 			return "OK"!
 		else:
-			return "Location references non-existing element!"!
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
 	else:
-		return "Location has non-string instance"!
+		return "Expected physical action value"!
 
-Element function constraint_ActionLanguage(model : Element, name : String):
-	Element self
-	self = model["model"][name]
-	if (is_physical_string(self)):
-		if (element_neq(import_node(self), read_root())):
+Element function constraint_call(model : Element, name : String):
+	if (is_physical_action(model["model"][name])):
+		if (cast_a2s(model["model"][name]) == "call"):
 			return "OK"!
 		else:
-			return "ActionLanguage references non-existing element!"!
+			return "Got wrong action primitive: " + cast_a2s(model["model"][name])!
 	else:
-		return "ActionLanguage has non-string value!"!
+		return "Expected physical action value"!
 
 Element function initialize_SCD(location : String):
 	if (element_neq(import_node(location), read_root())):
 		return import_node(location)!
 
 	Element scd
-	String al_location
-	al_location = "models/ActionLanguage"
-
 	scd = instantiate_bottom()
 
-	model_add_node(scd, "Element")
+	// Initial model, typed using LTM_bottom
 	model_add_node(scd, "Class")
-	model_add_node(scd, "Attribute")
-	model_add_node(scd, "SimpleAttribute")
+	model_add_node(scd, "Any")
 	model_add_node(scd, "String")
-	model_add_value(scd, "name_value", "name")
-	model_add_edge(scd, "Association", "Class", "Class")
-	model_add_edge(scd, "Inheritance", "Element", "Element")
-	model_add_edge(scd, "AttributeLink", "Element", "Attribute")
-	model_add_edge(scd, "attr_name", "AttributeLink", "String")
-	model_add_edge(scd, "attr_name_name", "attr_name", "name_value")
-	model_add_edge(scd, "class_inh_element", "Class", "Element")
-	model_add_edge(scd, "attribute_inh_element", "Attribute", "Element")
-	model_add_edge(scd, "simple_inh_attribute", "SimpleAttribute", "Attribute")
-	model_add_edge(scd, "association_inh_element", "Association", "Element")
-	model_add_edge(scd, "attributelink_inh_element", "AttributeLink", "Element")
-
-	// Retype to self
+	model_add_value(scd, "name", "name")
+	model_add_edge(scd, "Association", "Class", "Any")
+	model_add_edge(scd, "Inheritance", "Class", "Class")
+	model_add_edge(scd, "Association_attribute", "Association", "String")
+	model_add_edge(scd, "Association_name", "Association_attribute", "name")
+	model_add_edge(scd, "assoc_inh_class", "Association", "Class")
+	model_add_edge(scd, "class_inh_any", "Class", "Any")
+	model_add_edge(scd, "string_inh_any", "String", "Any")
+
+	// Retype to a "real" LTM, which happens to be itself
 	retype_model(scd, scd)
-	retype(scd, "Element", "Class")
 	retype(scd, "Class", "Class")
-	retype(scd, "Attribute", "Class")
-	retype(scd, "SimpleAttribute", "Class")
-	retype(scd, "String", "SimpleAttribute")
-	retype(scd, "name_value", "String")
+	retype(scd, "Any", "Class")
+	retype(scd, "String", "Class")
+	retype(scd, "name", "String")
 	retype(scd, "Association", "Association")
 	retype(scd, "Inheritance", "Association")
-	retype(scd, "AttributeLink", "Association")
-	retype(scd, "attr_name", "AttributeLink")
-	retype(scd, "attr_name_name", "attr_name")
-	retype(scd, "class_inh_element", "Inheritance")
-	retype(scd, "attribute_inh_element", "Inheritance")
-	retype(scd, "simple_inh_attribute", "Inheritance")
-	retype(scd, "association_inh_element", "Inheritance")
-	retype(scd, "attributelink_inh_element", "Inheritance")
+	retype(scd, "Association_attribute", "Association")
+	retype(scd, "Association_name", "Association_attribute")
+	retype(scd, "assoc_inh_class", "Inheritance")
+	retype(scd, "class_inh_any", "Inheritance")
+	retype(scd, "string_inh_any", "Inheritance")
 
 	// Add some attributes, now that it is an ordinary model
-	instantiate_node(scd, "SimpleAttribute", "Location")
-	instantiate_node(scd, "SimpleAttribute", "Natural")
-	instantiate_node(scd, "SimpleAttribute", "Boolean")
-	instantiate_link(scd, "AttributeLink", "attr_optional", "AttributeLink", "Boolean")
-	instantiate_attribute(scd, "attr_optional", "name", "optional")
-	instantiate_attribute(scd, "attr_optional", "optional", False)
-	instantiate_attribute(scd, "attr_name", "optional", False)
-
-	instantiate_node(scd, "Class", "ComplexAttribute")
-	instantiate_link(scd, "Inheritance", "", "ComplexAttribute", "Attribute")
-
-	model_define_attribute(scd, "Class", "lower_cardinality", True, "Natural")
-	model_define_attribute(scd, "Class", "upper_cardinality", True, "Natural")
-	model_define_attribute(scd, "Association", "source_lower_cardinality", True, "Natural")
-	model_define_attribute(scd, "Association", "target_lower_cardinality", True, "Natural")
-	model_define_attribute(scd, "Association", "source_upper_cardinality", True, "Natural")
-	model_define_attribute(scd, "Association", "target_upper_cardinality", True, "Natural")
-	model_define_attribute(scd, "ComplexAttribute", "type", False, "Location")
-
-	// Export already, to allow AL to pick it up
-	export_node(location, scd)
-	// Add in the Action Language metamodel
-	initialize_AL(location, al_location)
-
-	// Define additional attributes that define functions
-	instantiate_node(scd, "ComplexAttribute", "ActionLanguage")
-	instantiate_attribute(scd, "ActionLanguage", "type", al_location)
-	model_define_attribute(scd, "Element", "constraint", True, "ActionLanguage")
-
-	// Define some constraints
-	instantiate_attribute_code(scd, "Natural", "constraint", constraint_Natural)
-	instantiate_attribute_code(scd, "String", "constraint", constraint_String)
-	instantiate_attribute_code(scd, "Boolean", "constraint", constraint_Boolean)
-	instantiate_attribute_code(scd, "Location", "constraint", constraint_Location)
-	instantiate_attribute_code(scd, "ActionLanguage", "constraint", constraint_ActionLanguage)
-
-	instantiate_node(scd, "Class", "GlobalConstraint")
-	model_define_attribute(scd, "GlobalConstraint", "global_constraint", False, "ActionLanguage")
+	instantiate_node(scd, "Class", "Natural")
+	instantiate_link(scd, "Association", "lc", "Class", "Natural")
+	instantiate_attribute(scd, "lc", "name", "lower_cardinality")
+	instantiate_link(scd, "Association", "uc", "Class", "Natural")
+	instantiate_attribute(scd, "uc", "name", "upper_cardinality")
+	instantiate_link(scd, "Association", "slc", "Association", "Natural")
+	instantiate_attribute(scd, "slc", "name", "source_lower_cardinality")
+	instantiate_link(scd, "Association", "suc", "Association", "Natural")
+	instantiate_attribute(scd, "suc", "name", "source_upper_cardinality")
+	instantiate_link(scd, "Association", "tlc", "Association", "Natural")
+	instantiate_attribute(scd, "tlc", "name", "target_lower_cardinality")
+	instantiate_link(scd, "Association", "tuc", "Association", "Natural")
+	instantiate_attribute(scd, "tuc", "name", "target_upper_cardinality")
 
+	// Add in the Action Language metamodel
+	add_AL_to_MM(scd)
+
+	// Now still allow for constraints on classes
+	instantiate_link(scd, "Association", "constraint", "Class", "funcdef")
+	instantiate_attribute(scd, "constraint", "name", "constraint")
+
+	// Add constraints to all primitive classes
+	//add_constraint(scd, "if", constraint_if)
+	//add_constraint(scd, "while", constraint_while)
+	//add_constraint(scd, "break", constraint_break)
+	//add_constraint(scd, "continue", constraint_continue)
+	//add_constraint(scd, "assign", constraint_assign)
+	//add_constraint(scd, "return", constraint_return)
+	//add_constraint(scd, "output", constraint_output)
+	//add_constraint(scd, "input", constraint_input)
+	//add_constraint(scd, "declare", constraint_declare)
+	//add_constraint(scd, "global", constraint_global)
+	//add_constraint(scd, "access", constraint_access)
+	//add_constraint(scd, "constant", constraint_constant)
+	//add_constraint(scd, "resolve", constraint_resolve)
+	//add_constraint(scd, "call", constraint_call)
+
+	// And add some, to enforce correct physical types
+	add_constraint(scd, "Natural", constraint_natural)
+	add_constraint(scd, "String", constraint_string)
+
+	// Finally done, so export!
+	export_node(location, scd)
 	return scd!
 
 Element function initialize_PN(location_SCD : String, location_PN : String):
@@ -150,15 +234,24 @@ Element function initialize_PN(location_SCD : String, location_PN : String):
 	pn = instantiate_model(scd)
 	instantiate_node(pn, "Class", "Place")
 	instantiate_node(pn, "Class", "Transition")
-	instantiate_node(pn, "SimpleAttribute", "Natural")
+	instantiate_node(pn, "Class", "Natural")
 	instantiate_link(pn, "Association", "P2T", "Place", "Transition")
 	instantiate_link(pn, "Association", "T2P", "Transition", "Place")
-	model_define_attribute(pn, "Place", "tokens", False, "Natural")
-	model_define_attribute(pn, "P2T", "weight", False, "Natural")
-	model_define_attribute(pn, "T2P", "weight", False, "Natural")
+	instantiate_link(pn, "Association", "Place_tokens", "Place", "Natural")
+	instantiate_attribute(pn, "Place_tokens", "name", "tokens")
+	instantiate_attribute(pn, "Place_tokens", "target_lower_cardinality", 1)
+	instantiate_attribute(pn, "Place_tokens", "target_upper_cardinality", 1)
+	instantiate_link(pn, "Association", "P2T_weight", "P2T", "Natural")
+	instantiate_attribute(pn, "P2T_weight", "name", "weight")
+	instantiate_attribute(pn, "P2T_weight", "target_lower_cardinality", 1)
+	instantiate_attribute(pn, "P2T_weight", "target_upper_cardinality", 1)
+	instantiate_link(pn, "Association", "T2P_weight", "T2P", "Natural")
+	instantiate_attribute(pn, "T2P_weight", "name", "weight")
+	instantiate_attribute(pn, "T2P_weight", "target_lower_cardinality", 1)
+	instantiate_attribute(pn, "T2P_weight", "target_upper_cardinality", 1)
 
 	// Add constraint on the Natural
-	instantiate_attribute_code(pn, "Natural", "constraint", constraint_Natural)
+	add_constraint(pn, "Natural", constraint_natural)
 
 	export_node(location_PN, pn)
 
@@ -182,7 +275,7 @@ Element function initialize_bottom(location_bottom : String):
 
 	return ltm_bottom!
 
-Void function create_metamodels():
+Element function create_metamodels():
 	String location_SCD
 	String location_PN
 	String location_bottom
@@ -191,25 +284,16 @@ Void function create_metamodels():
 	location_PN = "models/PetriNets"
 	location_bottom = "models/LTM_bottom"
 
-	if (element_eq(import_node("models/PetriNets"), read_root())):
+	if (bool_not(dict_in(dict_read(dict_read(read_root(), "__hierarchy"), "models"), "SimpleClassDiagrams"))):
+		initialize_SCD(location_SCD)
+	if (bool_not(dict_in(dict_read(dict_read(read_root(), "__hierarchy"), "models"), "PetriNets"))):
 		initialize_PN(location_SCD, location_PN)
-	if (element_eq(import_node("models/LTM_bottom"), read_root())):
+	if (bool_not(dict_in(dict_read(dict_read(read_root(), "__hierarchy"), "models"), "LTM_bottom"))):
 		initialize_bottom(location_bottom)
 
-	return!
-
-Void function initialize_AL(scd_location : String, export_location : String):
-	// TODO this should be written in a file-based model and not created like this in the bootstrap
-	Element model
-	Element scd_model
-
-	if (element_neq(import_node(export_location), read_root())):
-		return!
+	return dict_read(dict_read(read_root(), "__hierarchy"), "models")!
 
-	scd_model = import_node(scd_location)
-	model = instantiate_model(scd_model)
-
-	instantiate_node(model, "Class", "Element")
+Void function add_AL_to_MM(model : Element):
 	instantiate_node(model, "Class", "Action")
 	instantiate_node(model, "Class", "Statement")
 	instantiate_node(model, "Class", "Expression")
@@ -229,17 +313,10 @@ Void function initialize_AL(scd_location : String, export_location : String):
 	instantiate_node(model, "Class", "input")
 	instantiate_node(model, "Class", "resolve")
 	instantiate_node(model, "Class", "call")
-	instantiate_node(model, "Class", "String")
-	instantiate_node(model, "SimpleAttribute", "StringAttr")
-	instantiate_node(model, "Class", "Initial")
-
-	instantiate_attribute(model, "Initial", "lower_cardinality", 1)
-	instantiate_attribute(model, "Initial", "upper_cardinality", 1)
-	instantiate_link(model, "Association", "initial_funcdef", "Initial", "Action")
-	instantiate_attribute(model, "initial_funcdef", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "initial_funcdef", "target_upper_cardinality", 1)
-
-	instantiate_link(model, "Inheritance", "", "Action", "Element")
+	instantiate_link(model, "Association", "dict_link", "Action", "Any")
+	instantiate_link(model, "Association", "to_str", "dict_link", "String")
+	instantiate_attribute(model, "to_str", "name", "name")
+	instantiate_link(model, "Inheritance", "", "Action", "Any")
 	instantiate_link(model, "Inheritance", "", "funcdef", "Action")
 	instantiate_link(model, "Inheritance", "", "param", "Action")
 	instantiate_link(model, "Inheritance", "", "Statement", "Action")
@@ -258,25 +335,20 @@ Void function initialize_AL(scd_location : String, export_location : String):
 	instantiate_link(model, "Inheritance", "", "access", "Expression")
 	instantiate_link(model, "Inheritance", "", "constant", "Expression")
 	instantiate_link(model, "Inheritance", "", "input", "Expression")
-	instantiate_link(model, "Inheritance", "", "String", "Element")
-
-	instantiate_link(model, "Association", "dict_link", "Action", "Element")
-	model_define_attribute(model, "dict_link", "name", False, "StringAttr")
-
-	instantiate_link(model, "Association", "Statement_next", "Statement", "Statement")
+	instantiate_link(model, "Association", "statement_next", "Statement", "Statement")
 	instantiate_link(model, "Association", "if_cond", "if", "Expression")
 	instantiate_link(model, "Association", "if_then", "if", "Statement")
 	instantiate_link(model, "Association", "if_else", "if", "Statement")
 	instantiate_link(model, "Association", "while_cond", "while", "Expression")
 	instantiate_link(model, "Association", "while_body", "while", "Statement")
-	instantiate_link(model, "Association", "assign_var", "assign", "resolve")
+	instantiate_link(model, "Association", "assign_var", "assign", "Any")
 	instantiate_link(model, "Association", "assign_value", "assign", "Expression")
 	instantiate_link(model, "Association", "break_while", "break", "while")
 	instantiate_link(model, "Association", "continue_while", "continue", "while")
 	instantiate_link(model, "Association", "return_value", "return", "Expression")
-	instantiate_link(model, "Association", "resolve_var", "resolve", "Element")
-	instantiate_link(model, "Association", "access_var", "access", "resolve")
-	instantiate_link(model, "Association", "constant_node", "constant", "Element")
+	instantiate_link(model, "Association", "resolve_var", "resolve", "Any")
+	instantiate_link(model, "Association", "access_var", "access", "Any")
+	instantiate_link(model, "Association", "constant_node", "constant", "Any")
 	instantiate_link(model, "Association", "output_node", "output", "Expression")
 	instantiate_link(model, "Association", "global_var", "global", "String")
 	instantiate_link(model, "Association", "param_name", "param", "String")
@@ -286,7 +358,7 @@ Void function initialize_AL(scd_location : String, export_location : String):
 	instantiate_link(model, "Association", "call_func", "call", "Expression")
 	instantiate_link(model, "Association", "call_params", "call", "param")
 	instantiate_link(model, "Association", "call_last_param", "call", "param")
-	instantiate_link(model, "Inheritance", "", "Statement_next", "dict_link")
+	instantiate_link(model, "Inheritance", "", "statement_next", "dict_link")
 	instantiate_link(model, "Inheritance", "", "if_cond", "dict_link")
 	instantiate_link(model, "Inheritance", "", "if_then", "dict_link")
 	instantiate_link(model, "Inheritance", "", "if_else", "dict_link")
@@ -310,47 +382,46 @@ Void function initialize_AL(scd_location : String, export_location : String):
 	instantiate_link(model, "Inheritance", "", "call_params", "dict_link")
 	instantiate_link(model, "Inheritance", "", "call_last_param", "dict_link")
 
+	// Add cardinalities on how many connections are allowed: one of each
+	instantiate_attribute(model, "statement_next", "target_upper_cardinality", 1)
 	instantiate_attribute(model, "if_cond", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "if_then", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "while_cond", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "while_body", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "assign_var", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "assign_value", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "break_while", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "continue_while", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "resolve_var", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "access_var", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "constant_node", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "output_node", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "global_var", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "param_name", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "param_value", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "funcdef_body", "target_lower_cardinality", 1)
-	instantiate_attribute(model, "call_func", "target_lower_cardinality", 1)
-
-	instantiate_attribute(model, "Statement_next", "target_upper_cardinality", 1)
 	instantiate_attribute(model, "if_cond", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "if_then", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "if_then", "target_upper_cardinality", 1)
 	instantiate_attribute(model, "if_else", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "while_cond", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "while_cond", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "while_body", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "while_body", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "assign_var", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "assign_var", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "assign_value", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "assign_value", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "break_while", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "break_while", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "continue_while", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "continue_while", "target_upper_cardinality", 1)
 	instantiate_attribute(model, "return_value", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "resolve_var", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "resolve_var", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "access_var", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "access_var", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "constant_node", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "constant_node", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "output_node", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "output_node", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "global_var", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "global_var", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "param_name", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "param_name", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "param_value", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "param_value", "target_upper_cardinality", 1)
 	instantiate_attribute(model, "param_next_param", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "funcdef_body", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "funcdef_body", "target_upper_cardinality", 1)
+	instantiate_attribute(model, "call_func", "target_lower_cardinality", 1)
 	instantiate_attribute(model, "call_func", "target_upper_cardinality", 1)
 	instantiate_attribute(model, "call_params", "target_upper_cardinality", 1)
 	instantiate_attribute(model, "call_last_param", "target_upper_cardinality", 1)
 
-	export_node(export_location, model)
 	return !

+ 0 - 415
bootstrap/mini_modify.alc

@@ -1,415 +0,0 @@
-include "primitives.alh"
-include "constructors.alh"
-include "object_operations.alh"
-include "library.alh"
-include "conformance_scd.alh"
-include "io.alh"
-include "metamodels.alh"
-include "modelling.alh"
-
-Boolean verbose = True
-
-String function pretty_print(model : Element):
-	Element keys_m
-	String type
-	String v_m
-	Element attr_list
-	Element attr_keys
-	String attr_key
-	String result
-
-	result = ""
-	keys_m = dict_keys(model["model"])
-
-	while (read_nr_out(keys_m) > 0):
-		v_m = set_pop(keys_m)
-		type = read_type(model["metamodel"], read_type(model, v_m))
-
-		if (bool_or(type == "Class", type == "Association")):
-			result = result + ((("  " + v_m) + " : ") + read_type(model, v_m))
-			result = result + "\n"
-			if (type == "Association"):
-				result = result + ((("    " + reverseKeyLookup(model["model"], read_edge_src(model["model"][v_m]))) + " --> ") + reverseKeyLookup(model["model"], read_edge_dst(model["model"][v_m])))
-				result = result + "\n"
-
-			// Defines attributes
-			attr_list = getInstantiatableAttributes(model, v_m)
-			attr_keys = dict_keys(attr_list)
-			while (0 < read_nr_out(attr_keys)):
-				attr_key = set_pop(attr_keys)
-				result = result + (((("      " + attr_key) + " : ") + cast_v2s(attr_list[attr_key])))
-				result = result + "\n"
-
-			// Has attributes
-			attr_list = getAttributeList(model, v_m)
-			attr_keys = dict_keys(attr_list)
-			while (0 < read_nr_out(attr_keys)):
-				attr_key = set_pop(attr_keys)
-				if (element_eq(read_attribute(model, v_m, attr_key), read_root())):
-					result = result + (((("      " + cast_v2s(attr_key)) + " : ") + cast_v2s(attr_list[attr_key])) + " = (undefined)")
-				else:
-					result = result + ((((("      " + cast_v2s(attr_key)) + " : ") + cast_v2s(attr_list[attr_key])) + " = ") + cast_v2s(read_attribute(model, v_m, attr_key)))
-				result = result + "\n"
-	return result!
-
-String function cmd_help_m(write : Boolean):
-	String result
-	result = ""
-	result = result + "Allowed operations:\n"
-	if (write):
-		result = result + " == READ/WRITE ==\n"
-		result = result + "  instantiate_node -- Create a new model element (node)\n"
-		result = result + "  instantiate_edge -- Create a new model element (edge)\n"
-		result = result + "  delete           -- Delete an existing element\n"
-		result = result + "  attr_add         -- Add an attribute to an element\n"
-		result = result + "  attr_add_code    -- Add a coded attribute to an element\n"
-		result = result + "  attr_del         -- Delete an attribute of an element\n"
-		result = result + "  attr_modify      -- Modify an attribute of an element\n"
-		result = result + "  retype           -- Change the type of an element\n"
-		result = result + "  upload           -- Upload a completely new model\n"
-	else:
-		result = result + " == READ-ONLY ==\n"
-	result = result + "  read_outgoing    -- Prints the list of outgoing links of an element\n"
-	result = result + "  read_incoming    -- Prints the list of incoming links to an element\n"
-	result = result + "  list             -- Prints the list of elements in the model\n"
-	result = result + "  list_full        -- Prints the list of all elements in the model\n"
-	result = result + "  types            -- Prints the list of elements that can be instantiated\n"
-	result = result + "  read             -- Prints the current state of a model element\n"
-	result = result + "  verify           -- Check whether the model conforms to the metamodel\n"
-	result = result + "  exit             -- Leave the modification interface\n"
-
-	return result!
-
-String function cmd_upload(write : Boolean, model : Element):
-	Element new_model
-	if (write):
-		output("Waiting for model constructors...")
-		new_model = construct_model_raw(model["metamodel"])
-		dict_overwrite(model, "model", new_model["model"])
-		dict_overwrite(model, "type_mapping", new_model["type_mapping"])
-		return "Success"!
-	else:
-		return "Permission denied to write"!
-
-String function cmd_instantiate_node(write : Boolean, model : Element, mm_type_name : String, element_name : String):
-	if (write):
-		if (dict_in(model["metamodel"]["model"], mm_type_name)):
-			if (dict_in(model["model"], element_name)):
-				return "Element exists: " + element_name!
-			else:
-				if (is_edge(model["metamodel"]["model"][mm_type_name])):
-					return "Element is not a node but an edge: " + mm_type_name!
-
-				element_name = instantiate_node(model, mm_type_name, element_name)
-				return "Success: " + element_name!
-		else:
-			return "Element not found: " + mm_type_name!
-	else:
-		return "Permission denied to write"!
-
-String function cmd_instantiate_edge(write : Boolean, model : Element, mm_type_name : String, element_name : String, source_name : String, target_name : String):
-	if (write):
-		if (dict_in(model["metamodel"]["model"], mm_type_name)):
-			if (dict_in(model["model"], element_name)):
-				return "Element exists: " + element_name!
-			else:
-				if (is_edge(model["metamodel"]["model"][mm_type_name])):
-					if (dict_in(model["model"], source_name)):
-						if (dict_in(model["model"], target_name)):
-							element_name = instantiate_link(model, mm_type_name, element_name, source_name, target_name)
-							return "Success: " + element_name!
-						else:
-							return "Element not found: " + target_name!
-					else:
-						return "Element not found: " + source_name!
-				else:
-					return "Element is a node not an edge: " + mm_type_name!
-		else:
-			return "Element not found: " + mm_type_name!
-	else:
-		return "Permission denied to write"!
-
-String function cmd_attr_add(write : Boolean, model : Element, element_name : String, attr_name : String, value : Element):
-	if (write):
-		if (dict_in(model["model"], element_name)):
-			Element attrs
-			attrs = getAttributeList(model, element_name)
-			if (set_in(dict_keys(attrs), attr_name)):
-				instantiate_attribute(model, element_name, attr_name, value)
-				return "Success"!
-			else:
-				return "Attribute not found: " + attr_name!
-		else:
-			return "Element not found: " + element_name!
-	else:
-		return "Permission denied to write"!
-
-String function cmd_attr_add_code(write : Boolean, model : Element, element_name : String, attr_name : String):
-	if (write):
-		if (dict_in(model["model"], element_name)):
-			Element attrs
-			attrs = getAttributeList(model, element_name)
-			if (set_in(dict_keys(attrs), attr_name)):
-				output("Waiting for code constructors...")
-				instantiate_attribute_code(model, element_name, attr_name, construct_function())
-				return "Success"!
-			else:
-				return "Attribute not found: " + attr_name!
-		else:
-			return "Element not found: " + element_name!
-	else:
-		return "Permission denied to write"!
-
-String function cmd_attr_del(write : Boolean, model : Element, element_name : String, attr_name : String):
-	if (write):
-		if (dict_in(model["model"], element_name)):
-			Element attrs
-			attrs = getAttributeList(model, element_name)
-			if (set_in(dict_keys(attrs), attr_name)):
-				unset_attribute(model, element_name, attr_name)
-				return "Success"!
-			else:
-				return "Attribute not found: " + attr_name!
-		else:
-			return "Element not found: " + element_name!
-	else:
-		return "Permission denied to write"!
-
-String function cmd_delete(write : Boolean, model : Element, element_name : String):
-	if (write):
-		if (dict_in(model["model"], element_name)):
-			model_delete_element(model, element_name)
-			return "Success"!
-		else:
-			return "Element not found: " + element_name!
-	else:
-		return "Permission denied to write"!
-
-String function cmd_list(model : Element):
-	Element keys_m
-	String v_m
-	String result
-	String typename
-
-	result = "Success: "
-	keys_m = dict_keys(model["model"])
-	while (read_nr_out(keys_m) > 0):
-		v_m = set_pop(keys_m)
-		// Filter out anonymous objects
-		if (bool_not(string_startswith(v_m, "__"))):
-			typename = read_type(model, v_m)
-			result = (result + ((("  " + v_m) + " : ") + typename)) + "\n"
-	
-	return result!
-
-String function cmd_list_full(model : Element):
-	Element keys_m
-	String v_m
-	String result
-	String typename
-
-	result = "Success: "
-	keys_m = dict_keys(model["model"])
-	while (read_nr_out(keys_m) > 0):
-		v_m = set_pop(keys_m)
-		// Filter out anonymous objects
-		typename = read_type(model, v_m)
-		result = (result + ((("  " + v_m) + " : ") + typename)) + "\n"
-	
-	return result!
-
-String function cmd_read_outgoing(model : Element, element_name : String, type : String):
-	String result
-	Element elems
-
-	result = "Success: "
-	if (dict_in(model["model"], element_name)):
-		elems = allOutgoingAssociationInstances(model, element_name, type)
-		while (read_nr_out(elems) > 0):
-			result = string_join(result, set_pop(elems)) + "\n"
-		return result!
-	else:
-		return "Element not found: " + element_name!
-
-String function cmd_read_incoming(model : Element, element_name : String, type : String):
-	String result
-	Element elems
-
-	result = "Success: "
-	if (dict_in(model["model"], element_name)):
-		elems = allIncomingAssociationInstances(model, element_name, type)
-		while (read_nr_out(elems) > 0):
-			result = string_join(result, set_pop(elems)) + "\n"
-		return result!
-	else:
-		return "Element not found: " + element_name!
-
-String function cmd_read(model : Element, element_name : String):
-	String result
-	Element attr_list
-	Element attr_keys
-	String attr_key
-
-	result = "Success: "
-	if (dict_in(model["model"], element_name)):
-		result = ((result + "ID: ") + element_name) + "\n"
-		result = ((result + "Type: ") + read_type(model, element_name)) + "\n"
-		if (is_edge(model["model"][element_name])):
-			result = ((result + "Source: ") + reverseKeyLookup(model["model"], read_edge_src(model["model"][element_name]))) + "\n"
-			result = ((result + "Destination: ") + reverseKeyLookup(model["model"], read_edge_dst(model["model"][element_name]))) + "\n"
-		if (has_value(model["model"][element_name])):
-			result = ((result + "Value: ") + cast_v2s(model["model"][element_name])) + "\n"
-		result = result + "Defines attributes:\n"
-		attr_list = getInstantiatableAttributes(model, element_name)
-		attr_keys = dict_keys(attr_list)
-		while (0 < read_nr_out(attr_keys)):
-			attr_key = set_pop(attr_keys)
-			result = ((((result + "  ") + attr_key) + " : ") + cast_v2s(attr_list[attr_key])) + "\n"
-		result = result + "Attributes:\n"
-		attr_list = getAttributeList(model, element_name)
-		attr_keys = dict_keys(attr_list)
-		while (0 < read_nr_out(attr_keys)):
-			attr_key = set_pop(attr_keys)
-			result = ((((((result + "  ") + cast_v2s(attr_key)) + " : ") + cast_v2s(attr_list[attr_key])) + " = ") + cast_v2s(read_attribute(model, element_name, attr_key))) + "\n"
-		return result!
-	else:
-		return "Element not found: " + element_name!
-
-String function cmd_types(model : Element):
-	Element keys_t
-	String v_t
-	String result
-
-	keys_t = dict_keys(model["metamodel"]["model"])
-	result = "Success: "
-	while (read_nr_out(keys_t) > 0):
-		v_t = set_pop(keys_t)
-		if (bool_not(string_startswith(v_t, "__"))):
-			result = (result + string_join(("  " + v_t) + " : ", read_type(model["metamodel"], v_t))) + "\n"
-
-	return result!
-
-String function cmd_retype(write : Boolean, model : Element, element_name : String, new_type : String):
-	if (write):
-		if (dict_in(model["model"], element_name)):
-			if (dict_in(model["metamodel"]["model"], new_type)):
-				retype(model, element_name, new_type)
-				return "Success"!
-			else:
-				return "Element not found: " + new_type!
-		else:
-			return "Element not found: " + element_name!
-	else:
-		return "Permission denied to write"!
-
-String function cmd_read_association_source(write : Boolean, model : Element, element_name : String):
-	if (dict_in(model["model"], element_name)):
-		if (is_edge(model["model"][element_name])):
-			return "Success: " + readAssociationSource(model, element_name)!
-		else:
-			return "Not an association: " + element_name!
-	else:
-		return "Element not found: " + element_name!
-
-String function cmd_read_association_destination(write : Boolean, model : Element, element_name : String):
-	if (dict_in(model["model"], element_name)):
-		if (is_edge(model["model"][element_name])):
-			return "Success: " + readAssociationDestination(model, element_name)!
-		else:
-			return "Not an association: " + element_name!
-	else:
-		return "Element not found: " + element_name!
-
-Element function modify(model : Element, write : Boolean):
-	String cmd
-
-	output("Model loaded, ready for commands!")
-
-	while (True):
-		cmd = input()
-		if (cmd == "help"):
-			output(cmd_help_m(write))
-		elif (cmd == "exit"):
-			return model!
-		elif (cmd == "upload"):
-			output(cmd_upload(write, model))
-		elif (cmd == "instantiate_node"):
-			output(cmd_instantiate_node(write, model, single_input("Type?"), single_input("Name?")))
-		elif (cmd == "instantiate_edge"):
-			output(cmd_instantiate_edge(write, model, single_input("Type?"), single_input("Name?"), single_input("Source?"), single_input("Target?")))
-		elif (cmd == "attr_add"):
-			output(cmd_attr_add(write, model, single_input("Name?"), single_input("Attribute name?"), single_input("Value?")))
-		elif (cmd == "attr_add_code"):
-			output(cmd_attr_add_code(write, model, single_input("Name?"), single_input("Attribute name?")))
-		elif (cmd == "attr_del"):
-			output(cmd_attr_del(write, model, single_input("Name?"), single_input("Attribute_name?")))
-		elif (cmd == "delete"):
-			output(cmd_delete(write, model, single_input("Name?")))
-		elif (cmd == "nice_list"):
-			output(pretty_print(model))
-		elif (cmd == "list"):
-			output(cmd_list(model))
-		elif (cmd == "list_full"):
-			output(cmd_list_full(model))
-		elif (cmd == "read_outgoing"):
-			output(cmd_read_outgoing(model, single_input("Name?"), single_input("Type?")))
-		elif (cmd == "read_incoming"):
-			output(cmd_read_incoming(model, single_input("Name?"), single_input("Type?")))
-		elif (cmd == "read"):
-			output(cmd_read(model, single_input("Name?")))
-		elif (cmd == "verify"):
-			output("Success: " + conformance_scd(model))
-		elif (cmd == "types"):
-			output(cmd_types(model))
-		elif (cmd == "retype"):
-			output(cmd_retype(write, model, single_input("Name?"), single_input("New type?")))
-		elif (cmd == "read_association_source"):
-			output(cmd_read_association_source(write, model, single_input("Name?")))
-		elif (cmd == "read_association_destination"):
-			output(cmd_read_association_destination(write, model, single_input("Name?")))
-		else:
-			output("Unknown command while modelling: " + cast_v2s(cmd))
-			output("Use command 'help' to get a list of available commands")
-	return model!
-
-String function single_input(prompt : String):
-	if (verbose):
-		output(prompt)
-
-	return input()!
-
-Element function set_input(prompt : String):
-	Element result
-	Element inp
-
-	if (verbose):
-		output(prompt)
-		output("-- Set input: empty string to terminate set")
-
-	result = create_node()
-	while (True):
-		inp = input()
-		if (value_eq(inp, "")):
-			return result!
-		else:
-			set_add(result, inp)
-
-Element function dict_input(prompt : String):
-	Element result
-	Element key
-
-	if (verbose):
-		output(prompt)
-		output("-- Dict input: empty key to terminate dict")
-
-	result = create_node()
-	while (True):
-		key = input()
-		if (value_eq(key, "")):
-			return result!
-		else:
-			dict_add(result, key, input())
-
-Void function set_verbose(v : Boolean):
-	verbose = v
-	return!

+ 95 - 218
bootstrap/model_management.alc

@@ -12,11 +12,9 @@ Element function model_fuse(models : Element):
 	String model_name
 	Element model
 	Element keys
-	Element second_keys
 	String key
 	Element selected_MM
 	String type
-	Element reverse
 
 	// Read out some data first
 	tagged_model = set_pop(models)
@@ -24,73 +22,62 @@ Element function model_fuse(models : Element):
 	new_model = instantiate_model(tagged_model[1]["metamodel"])
 
 	// Do the iteration
-	while (read_nr_out(models) > 0):
+	while (read_nr_out(models)):
 		tagged_model = set_pop(models)
 		model_name = string_join(list_read(tagged_model, 0), "/")
 		model = list_read(tagged_model, 1)
 
-		reverse = make_reverse_dictionary(model["model"])
-
 		// Add all elements from 'model', but prepend it with the 'model_name'
-		keys = dict_keys(model["model"])
-		second_keys = create_node()
-
+		keys = set_to_list(dict_keys(model["model"]))
 		while (read_nr_out(keys) > 0):
-			key = set_pop(keys)
+			key = list_pop(keys, 0)
 			type = read_type(model, key)
 
 			if (is_edge(model["model"][key])):
 				String src
 				String dst
-				src = string_join(model_name, reverse[cast_id2s(read_edge_src(model["model"][key]))])
-				dst = string_join(model_name, reverse[cast_id2s(read_edge_dst(model["model"][key]))])
+				src = model_name + reverseKeyLookup(model["model"], read_edge_src(model["model"][key]))
+				dst = model_name + reverseKeyLookup(model["model"], read_edge_dst(model["model"][key]))
 				if (bool_and(dict_in(new_model["model"], src), dict_in(new_model["model"], dst))):
 					instantiate_link(new_model, type, model_name + key, src, dst)
 				else:
-					set_add(second_keys, key)
+					list_append(keys, key)
 			elif (has_value(model["model"][key])):
 				instantiate_value(new_model, type, model_name + key, model["model"][key])
 			else:
 				instantiate_node(new_model, type, model_name + key)
 
-			if (read_nr_out(keys) == 0):
-				keys = second_keys
-				second_keys = create_node()
-
 	return new_model!
 
 Element function model_copy(src_model : Element):
 	Element dst_model
+	Element queue
 	Element name
-	Element keys
-	Element second_keys
 	String type
 
-	Element reverse
-	reverse = make_reverse_dictionary(src_model["model"])
-
 	dst_model = instantiate_model(src_model["metamodel"])
-	keys = dict_keys(src_model["model"])
-	second_keys = create_node()
+	dict_add(dst_model, "model", create_node())
+	dict_add(dst_model, "type_mapping", create_node())
 
-	while (read_nr_out(keys) > 0):
-		name = set_pop(keys)
+	queue = set_to_list(dict_keys(src_model["model"]))
+
+	while (read_nr_out(queue) > 0):
+		name = list_pop(queue, 0)
 
 		if (is_edge(src_model["model"][name])):
 			// Is an edge, so potentially queue it
 			String src
 			String dst
 
-			src = reverse[cast_id2s(read_edge_src(src_model["model"][name]))]
-			dst = reverse[cast_id2s(read_edge_dst(src_model["model"][name]))]
-
+			src = reverseKeyLookup(src_model["model"], read_edge_src(src_model["model"][name]))
+			dst = reverseKeyLookup(src_model["model"], read_edge_dst(src_model["model"][name]))
 			type = read_type(src_model, name)
 
 			if (bool_and(dict_in(dst_model["model"], src), dict_in(dst_model["model"], dst))):
 				// All present, so create the link between them
 				instantiate_link(dst_model, type, name, src, dst)
 			else:
-				set_add(second_keys, name)
+				list_append(queue, name)
 
 		elif (has_value(src_model["model"][name])):
 			// Has a value, so copy that as well
@@ -102,10 +89,6 @@ Element function model_copy(src_model : Element):
 			type = read_type(src_model, name)
 			instantiate_node(dst_model, type, name)
 
-		if (read_nr_out(keys) == 0):
-			keys = second_keys
-			second_keys = create_node()
-
 	return dst_model!
 
 Element function model_retype_on_name(model : Element, new_MM : Element, operation : String, name : String):
@@ -126,222 +109,116 @@ Element function model_retype_on_name(model : Element, new_MM : Element, operati
 			if (operation == "+"):
 				// Keep all, but augment typename
 				dict_delete(model["type_mapping"], key)
-				dict_add_fast(model["type_mapping"], key, name + type)
+				dict_add(model["type_mapping"], key, name + type)
 			elif (operation == "-"):
 				// Keep only if typename beginning matches and remove from typename
 				if (string_startswith(type, name)):
 					dict_delete(model["type_mapping"], key)
-					dict_add_fast(model["type_mapping"], key, string_substr(type, length, string_len(type)))
+					dict_add(model["type_mapping"], key, string_substr(type, length, string_len(type)))
 				else:
 					model_delete_element(model, key)
 
 	dict_delete(model, "metamodel")
-	dict_add_fast(model, "metamodel", new_MM)
+	dict_add(model, "metamodel", new_MM)
 
 	return model!
 
-Element function model_join(models : Element, metamodel : Element, tracability_model : Element):
-	Element new_model
-	Element tagged_model
-	String retyping_key
-	Element elem_map
-	Element model
-	Element keys
-	String new_name
-	Element second_keys
+Void function model_join(dst_model : Element, src_model : Element, retyping_key : String):
+	Element queue
+	Element mapping
+	String name
+	String type
 	String src
 	String dst
-	String key
-	String type
-
-	new_model = instantiate_model(metamodel)
-	elem_map = create_node()
-
-	// Do the iteration
-	while (read_nr_out(models) > 0):
-		tagged_model = set_pop(models)
-		retyping_key = string_join(list_read(tagged_model, 0), "/")
-		model = list_read(tagged_model, 1)
-
-		// Add all elements from 'model'
-		keys = dict_keys(model["model"])
-		second_keys = create_node()
-
-		while (read_nr_out(keys) > 0):
-			// Copy the new element
-			key = set_pop(keys)
-			type = read_type(model, key)
-
-			if (is_edge(model["model"][key])):
-				src = cast_id2s(read_edge_src(model["model"][key]))
-				dst = cast_id2s(read_edge_dst(model["model"][key]))
-				if (bool_and(dict_in(elem_map, src), dict_in(elem_map, dst))):
-					new_name = instantiate_link(new_model, retyping_key + type, key, elem_map[src], elem_map[dst])
-				else:
-					set_add(second_keys, key)
-					new_name = ""
-			elif (has_value(model["model"][key])):
-				new_name = instantiate_value(new_model, retyping_key + type, key, model["model"][key])
-			else:
-				new_name = instantiate_node(new_model, retyping_key + type, key)
 
-			if (new_name != ""):
-				// Add the new name to a map which registers the mapping to the new name
-				dict_add_fast(elem_map, cast_id2s(model["model"][key]), new_name)
+	queue = set_to_list(dict_keys(src_model["model"]))
+	mapping = create_node()
 
-			if (read_nr_out(keys) == 0):
-				keys = second_keys
-				second_keys = create_node()
+	while (read_nr_out(queue) > 0):
+		name = list_pop(queue, 0)
 
-	// Now link in the tracability model
-	// Go over all TracabilityLink elements and connect them in the merged model as well
+		type = read_type(src_model, name)
 
-	if (element_neq(tracability_model, read_root())):
-		Element tracability_links
-		String tracability_link
-		String new_name_src
-		String new_name_dst
+		if (is_edge(src_model["model"][name])):
+			// Is an edge, so potentially queue it
+			String src
+			String dst
 
-		tracability_links = allInstances(tracability_model, "TracabilityLink")
+			src = reverseKeyLookup(src_model["model"], read_edge_src(src_model["model"][name]))
+			dst = reverseKeyLookup(src_model["model"], read_edge_dst(src_model["model"][name]))
 
-		while (read_nr_out(tracability_links) > 0):
-			tracability_link = set_pop(tracability_links)
+			if (bool_and(dict_in(mapping, src), dict_in(mapping, dst))):
+				// All present, so create the link between them
+				dict_add(mapping, name, instantiate_link(dst_model, retyping_key + type, "", mapping[src], mapping[dst]))
+			else:
+				list_append(queue, name)
 
-			// Get necessary information from the tracability link
+		elif (has_value(src_model["model"][name])):
+			// Has a value, so copy that as well
+			dict_add(mapping, name, instantiate_value(dst_model, retyping_key + type, "", src_model["model"][name]))
 
-			new_name_src = elem_map[cast_id2s(read_edge_src(tracability_model["model"][tracability_link]))]
-			new_name_dst = elem_map[cast_id2s(read_edge_dst(tracability_model["model"][tracability_link]))]
-			type = read_attribute(tracability_model, tracability_link, "type")
+		else:
+			// Is a node
+			dict_add(mapping, name, instantiate_node(dst_model, retyping_key + type, ""))
 
-			// Connect the two with the info we have
-			new_name = instantiate_link(new_model, type, "", new_name_src, new_name_dst)
+	return!
+	
+Element function model_split(src_model : Element, target_metamodel : Element, retyping_key : String):
+	Element dst_model
 
-			if (new_name == ""):
-				log("ERROR: could not create a tracability link; ignoring")
+	dst_model = instantiate_model(target_metamodel)
 
-	return new_model!
-	
-Element function model_split(merged_model : Element, models : Element, tracability : Boolean):
-	if (read_nr_out(models) == 0):
-		// No results needed, so stop immediately unless tracability is True
-		if (bool_not(tracability)):
-			return create_node()!
-
-	Element result
-	Element metamodel
-	Element model_tuple
-	Element tracability_model
-	Element keys
-	String key
-	String src
-	String dst
-	Element reverse
+	Element queue
 	Element mapping
-	String retyping_key
-	String original_type
-	Element elem
-	Element second_keys
+	String name
 	String type
-	Element splitted
-	String source
-	String target
-	String link
-	String src_name
-	String dst_name
-
-	result = create_node()
-	tracability_model = instantiate_model(import_node("models/Tracability"))
-	reverse = make_reverse_dictionary(merged_model["model"])
+	String src
+	String dst
+	Integer length
+	String new_type
+
+	queue = set_to_list(dict_keys(src_model["model"]))
 	mapping = create_node()
-	second_keys = create_node()
+	length = string_len(retyping_key)
 
-	while (read_nr_out(models) > 0):
-		model_tuple = set_pop(models)
-		retyping_key = model_tuple[0]
-		metamodel = model_tuple[1]
-		dict_add_fast(result, retyping_key, instantiate_model(metamodel))
+	while (read_nr_out(queue) > 0):
+		name = list_pop(queue, 0)
 
-	keys = dict_keys(merged_model["model"])
-	while (read_nr_out(keys) > 0):
-		key = set_pop(keys)
-		elem = merged_model["model"][key]
-		type = read_type(merged_model, key)
-		splitted = string_split(type, "/")
-
-		if (list_len(splitted) == 1):
-			// Only one, so no split possible
-			// Indicates a tracability element!
-			if (bool_and(tracability, is_edge(elem))):
-				// Got a tracability link!
-				// Is always an edge (for now?)
-				// Find out source and target and hope that they are already present
-				log("Create tracability link in model!")
-				src = reverse[cast_id2s(read_edge_src(elem))]
-				dst = reverse[cast_id2s(read_edge_dst(elem))]
-
-				src_name = list_read(string_split(read_type(merged_model, src), "/"), 0)
-				dst_name = list_read(string_split(read_type(merged_model, dst), "/"), 0)
-
-				log("Source model name: " + cast_v2s(src_name))
-				log("Destination model name: " + cast_v2s(dst_name))
-				log("Result: " + dict_to_string(result))
-
-				// Check if we actually keep both models around, as otherwise it is useless anyway
-				if (bool_and(dict_in(result, src_name), dict_in(result, dst_name))):
-					if (bool_and(dict_in(mapping, src), dict_in(mapping, dst))):
-						// All present, so create the link between them
-						Element src_model
-						Element dst_model
-
-						src_model = result[src_name]
-						dst_model = result[dst_name]
-
-						source = reuse_element(tracability_model, "Reference", "", src_model["model"][mapping[src]])
-						target = reuse_element(tracability_model, "Reference", "", dst_model["model"][mapping[dst]])
-
-						link = instantiate_link(tracability_model, "TracabilityLink", "", source, target)
-						instantiate_attribute(tracability_model, link, "type", type)
-					else:
-						// Not yet available!
-						set_add(second_keys, key)
-		else:
-			retyping_key = splitted[0]
-
-			if (dict_in(result, retyping_key)):
-				original_type = splitted[1]
-
-				if (is_edge(elem)):
-					// Is an edge, so potentially queue it
-					src = reverse[cast_id2s(read_edge_src(elem))]
-					dst = reverse[cast_id2s(read_edge_dst(elem))]
-
-					if (bool_and(dict_in(mapping, src), dict_in(mapping, dst))):
-						// All present, so create the link between them
-						// Though we first check the model to which it was mapped, as this should be the same as we have now
-						if (bool_and(dict_in(result[retyping_key]["model"], mapping[src]), dict_in(result[retyping_key]["model"], mapping[dst]))):
-							// The matching worked fine
-							dict_add_fast(mapping, key, instantiate_link(result[retyping_key], original_type, "", mapping[src], mapping[dst]))
-						else:
-							log("ERROR mapping: source/target mapped to model, but not found in expected model; ignoring")
-					else:
-						// Still source or destination in the queue, so we wait for that
-						set_add(second_keys, key)
-
-				elif (has_value(elem)):
-					// Has a value, so copy that as well
-					dict_add_fast(mapping, key, instantiate_value(result[retyping_key], original_type, "", elem))
+		type = read_type(src_model, name)
+		if (string_startswith(type, retyping_key)):
+			new_type = string_substr(type, length, string_len(type))
+			if (is_edge(src_model["model"][name])):
+				// Is an edge, so potentially queue it
+				String src
+				String dst
 
+				src = reverseKeyLookup(src_model["model"], read_edge_src(src_model["model"][name]))
+				dst = reverseKeyLookup(src_model["model"], read_edge_dst(src_model["model"][name]))
+
+				if (bool_and(dict_in(mapping, src), dict_in(mapping, dst))):
+					// All present, so create the link between them
+					dict_add(mapping, name, instantiate_link(dst_model, new_type, "", mapping[src], mapping[dst]))
+				elif (bool_not(bool_or(set_in(queue, src), set_in(queue, dst)))):
+					// Source/target not in the queue, but we need it to split!
+					// This is an error as it indicates problems with links crossing different formalisms
+					log("ERROR: source/target of link to be included is not included!")
+					log("Source: " + src)
+					log("  type: " + read_type(src_model, src))
+					log("Destination: " + dst)
+					log("  type: " + read_type(src_model, dst))
+					log("For link: " + name)
+					log("  type: " + type)
+					return create_node()!
 				else:
-					// Is a node
-					dict_add_fast(mapping, key, instantiate_node(result[retyping_key], original_type, ""))
+					// Still source or destination in the queue, so we wait for that
+					list_append(queue, name)
 
-		if (read_nr_out(keys) == 0):
-			keys = second_keys
-			second_keys = create_node()
+			elif (has_value(src_model["model"][name])):
+				// Has a value, so copy that as well
+				dict_add(mapping, name, instantiate_value(dst_model, new_type, "", src_model["model"][name]))
 
-	// Finally, we also add tracability information as a separate model
-	if (tracability):
-		dict_add_fast(result, "__tracability", tracability_model)
-		log("Tracability model created with # links = " + cast_v2s(read_nr_out(tracability_model["model"])))
+			else:
+				// Is a node
+				dict_add(mapping, name, instantiate_node(dst_model, new_type, ""))
 
-	return result!
+	return dst_model!

+ 163 - 177
bootstrap/modelling.alc

@@ -22,8 +22,8 @@ Element function instantiate_bottom():
 	new_model = create_node()
 
 	// Add an empty model and empty type mapping
-	dict_add_fast(new_model, "model", create_node())
-	dict_add_fast(new_model, "type_mapping", create_node())
+	dict_add(new_model, "model", create_node())
+	dict_add(new_model, "type_mapping", create_node())
 
 	// Return the created model
 	return new_model!
@@ -36,7 +36,7 @@ String function model_add_node(model : Element, name : String):
 
 	new_node = create_node()
 	actual_name = instantiated_name(new_node, name)
-	dict_add_fast(model["model"], actual_name, new_node)
+	dict_add(model["model"], actual_name, new_node)
 
 	return actual_name!
 
@@ -45,7 +45,7 @@ String function model_add_value(model : Element, name : String, value : Element)
 	String actual_name
 
 	actual_name = instantiated_name(value, name)
-	dict_add_fast(model["model"], actual_name, value)
+	dict_add(model["model"], actual_name, value)
 
 	return actual_name!
 
@@ -68,15 +68,15 @@ String function model_add_edge(model : Element, name : String, source : String,
 
 	new_edge = create_edge(model["model"][source], model["model"][destination])
 	actual_name = instantiated_name(new_edge, name)
-	dict_add_fast(model["model"], actual_name, new_edge)
+	dict_add(model["model"], actual_name, new_edge)
 
 	return actual_name!
 
 Void function retype_model(model : Element, metamodel : Element):
 	// Remove the type mapping and add a new one for the specified metamodel
 	dict_delete(model, "type_mapping")
-	dict_add_fast(model, "type_mapping", create_node())
-	dict_add_fast(model, "metamodel", metamodel)
+	dict_add(model, "type_mapping", create_node())
+	dict_add(model, "metamodel", metamodel)
 	return!
 
 Void function retype(model : Element, element : String, type : String):
@@ -86,7 +86,7 @@ Void function retype(model : Element, element : String, type : String):
 	if (dict_in(model["type_mapping"], element)):
 		dict_delete(model["type_mapping"], element)
 
-	dict_add_fast(model["type_mapping"], element, type)
+	dict_add(model["type_mapping"], element, type)
 
 	return!
 
@@ -98,21 +98,9 @@ Element function instantiate_model(metamodel : Element):
 	retype_model(model, metamodel)
 	return model!
 
-String function reuse_element(model : Element, type_name : String, instance_name : String, element : Element):
-	String actual_name
-
-	if (bool_not(dict_in(model["metamodel"]["model"], type_name))):
-		log("ERROR: (instantiate_node) no such type in metamodel: " + type_name)
-		log("    for " + instance_name)
-		return ""!
-
-	actual_name = instantiated_name(element, instance_name)
-	dict_add(model["model"], actual_name, element)
-	dict_add_fast(model["type_mapping"], actual_name, type_name)
-
-	return actual_name!
-
 String function instantiate_node(model : Element, type_name : String, instance_name : String):
+	// Create a node typed by a node from the metamodel
+	// Basically create a node and type it immediately
 	String actual_name
 
 	if (bool_not(dict_in(model["metamodel"]["model"], type_name))):
@@ -120,25 +108,24 @@ String function instantiate_node(model : Element, type_name : String, instance_n
 		log("    for " + instance_name)
 		return ""!
 
-	Element value
-	value = create_node()
+	actual_name = model_add_node(model, instance_name)
+	retype(model, actual_name, type_name)
 
-	actual_name = instantiated_name(value, instance_name)
-	dict_add_fast(model["model"], actual_name, value)
-	dict_add_fast(model["type_mapping"], actual_name, type_name)
 	return actual_name!
 
 String function instantiate_value(model : Element, type_name : String, instance_name : String, value : Element):
+	// Create a node typed by a node from the metamodel
+	// Basically create a node and type it immediately
 	String actual_name
 
 	if (bool_not(dict_in(model["metamodel"]["model"], type_name))):
 		log("ERROR: (instantiate_value) no such type in metamodel: " + type_name)
 		log("     for " + instance_name)
 		return ""!
-	
-	actual_name = instantiated_name(value, instance_name)
-	dict_add_fast(model["model"], actual_name, value)
-	dict_add_fast(model["type_mapping"], actual_name, type_name)
+
+	actual_name = model_add_value(model, instance_name, value)
+	retype(model, actual_name, type_name)
+
 	return actual_name!
 
 String function find_attribute_type(model : Element, elem : String, name : String):
@@ -160,37 +147,6 @@ String function find_attribute_type(model : Element, elem : String, name : Strin
 		result = reverseKeyLookup(model["metamodel"]["model"], dict_read_edge(model["metamodel"]["model"][mm_elem], name))
 		return result!
 
-Element function get_subclasses(model : Element, name : String):
-	Element result
-	Integer i
-	Integer j
-	Integer num_edges
-	Element edge
-	String elem
-	Element nodes
-
-	nodes = create_node()
-	set_add(nodes, name)
-
-	// Initialize empty set
-	result = create_node()
-	i = 0
-
-	while (list_len(nodes) > 0):
-		elem = set_pop(nodes)
-		if (bool_not(set_in(result, elem))):
-			create_edge(result, elem)
-			// Read out all incoming edges
-			num_edges = read_nr_in(model["model"][elem])
-			j = 0
-			while (j < num_edges):
-				edge = read_in(model["model"][elem], j)
-				if (value_eq(model["type_mapping"][reverseKeyLookup(model["model"], edge)], "Inheritance")):
-					set_add(nodes, reverseKeyLookup(model["model"], read_edge_src(edge)))
-				j = j + 1
-
-	return result!
-
 Element function get_superclasses(model : Element, name : String):
 	Element result
 	Integer i
@@ -199,9 +155,11 @@ Element function get_superclasses(model : Element, name : String):
 	Element edge
 	String elem
 	Element nodes
+	Element inheritance
 
 	nodes = create_node()
 	set_add(nodes, name)
+	inheritance = "Inheritance"
 
 	// Initialize empty set
 	result = create_node()
@@ -216,7 +174,7 @@ Element function get_superclasses(model : Element, name : String):
 			j = 0
 			while (j < num_edges):
 				edge = read_out(model["model"][elem], j)
-				if (value_eq(model["type_mapping"][reverseKeyLookup(model["model"], edge)], "Inheritance")):
+				if (value_eq(model["type_mapping"][reverseKeyLookup(model["model"], edge)], inheritance)):
 					set_add(nodes, reverseKeyLookup(model["model"], read_edge_dst(edge)))
 				j = j + 1
 
@@ -249,15 +207,11 @@ Void function instantiate_attribute(model : Element, element : String, attribute
 	String attr_type
 	String attr_name
 
-	if (element_neq(read_attribute(model, element, attribute_name), read_root())):
-		unset_attribute(model, element, attribute_name)
-
 	attr_type = find_attribute_type(model, element, attribute_name)
 
 	if (attr_type == ""):
 		log("Could not find attribute " + cast_v2s(attribute_name))
 		log("For element " + element)
-		log("Type: " + read_type(model, element))
 		return!
 
 	if (has_value(value)):
@@ -285,23 +239,10 @@ Void function instantiate_attribute_ref(model : Element, element : String, attri
 
 	return!
 
-Void function add_code_model(model : Element, export_name : String, code : Element):
-	Element code_model
-	code_model = instantiate_model(model)
-	add_AL(code_model, code)
-	export_node(export_name, code_model)
-
-	return !
-
 Void function instantiate_attribute_code(model : Element, element : String, attribute_name : String, code : Element):
-	// First create a new model for the AL part
-	String location
-	location = "code/" + cast_id2s(code)
-
-	add_code_model(import_node("models/ActionLanguage"), location, code)
-
-	// Now link it with a complex attribute
-	instantiate_attribute(model, element, attribute_name, location)
+	String ref
+	ref = add_AL(model, code)
+	instantiate_existing_attribute(model, element, attribute_name, ref)
 
 	return!
 
@@ -339,32 +280,19 @@ String function instantiate_link(model : Element, type : String, name : String,
 			type = set_pop(options)
 		elif (read_nr_out(options) == 0):
 			log("ERROR: cannot find possible link between entries")
-			log("    for " + source)
-			log("    to " + destination)
 			return ""!
 		else:
 			log("ERROR: too many possible links between entries")
-			log("   options: " + set_to_string(options))
 			return ""!
 
-	if (bool_not(dict_in(model["model"], source))):
-		log("ERROR: source of link undefined: " + source)
-		return ""!
-
-	if (bool_not(dict_in(model["model"], destination))):
-		log("ERROR: destination of link undefined: " + destination)
-		return ""!
-
 	if (bool_not(dict_in(model["metamodel"]["model"], type))):
 		log("ERROR: (instantiate_link) no such type in metamodel: " + type)
 		log("    for " + name)
 		return ""!
+
+	actual_name = model_add_edge(model, name, source, destination)
 	
-	Element v
-	v = create_edge(model["model"][source], model["model"][destination])
-	actual_name = instantiated_name(v, name)
-	dict_add_fast(model["model"], actual_name, v)
-	dict_add_fast(model["type_mapping"], actual_name, type)
+	retype(model, actual_name, type)
 	return actual_name!
 
 Void function model_delete_element(model : Element, name : String):
@@ -377,50 +305,38 @@ Void function model_delete_element(model : Element, name : String):
 
 	return!
 
-String function model_define_attribute(model : Element, elem : String, name : String, optional : Boolean, type : String):
+String function model_define_attribute(model : Element, elem : String, name : String, type : String):
 	// Create the necessary links to make it an attribute
 	String edge_name
 
-	edge_name = (elem + "_") + name
-	while (dict_in(model["model"], edge_name)):
-		// Already exists, so make random name
-		edge_name = edge_name + cast_id2s(model["model"][elem])
-		log("Name clash detected for attribute: try new name: " + edge_name)
-
-	edge_name = instantiate_link(model, "AttributeLink", edge_name, elem, type)
+	edge_name = instantiate_link(model, "Association", "", elem, type)
 	instantiate_attribute(model, edge_name, "name", name)
-	instantiate_attribute(model, edge_name, "optional", optional)
 
 	return edge_name!
 
 Element function read_attribute(model : Element, element : String, attribute : String):
-	if (dict_in(model["model"], element)):
-		Integer i
-		Integer count
-		Element edge
-		Element edge_type
-		Element elem
-		Element typing
-		Element name
-
-		elem = model["model"][element]
-		typing = model["type_mapping"]
-		count = read_nr_out(elem)
-
-		i = 0
-		while (i < count):
-			edge = read_out(elem, i)
-			name = reverseKeyLookup(model["model"], edge)
-			if (dict_in(typing, name)):
-				edge_type = model["metamodel"]["model"][typing[name]]
-				if (element_eq(edge_type, dict_read_edge(read_edge_src(edge_type), attribute))):
-					return read_edge_dst(edge)!
-			i = i + 1
+	Integer i
+	Integer count
+	Element edge
+	String edge_type_name
+	Element elem
+	Element typing
+	Element name
 
-	else:
-		log("Element does not exist: " + element)
+	elem = model["model"][element]
+	typing = model["type_mapping"]
+	count = read_nr_out(elem)
+
+	i = 0
+	while (i < count):
+		edge = read_out(elem, i)
+		name = reverseKeyLookup(model["model"], edge)
+		if (dict_in(typing, name)):
+			edge_type_name = typing[name]
+			if (edge_type_name == reverseKeyLookup(model["metamodel"]["model"], dict_read_edge(read_edge_src(model["metamodel"]["model"][edge_type_name]), attribute))):
+				return read_edge_dst(edge)!
+		i = i + 1
 
-	// Not found: either element doesn't exist, or we couldn't find it
 	return read_root()!
 
 Void function unset_attribute(model : Element, element : String, attribute : String):
@@ -436,7 +352,7 @@ Void function unset_attribute(model : Element, element : String, attribute : Str
 		attr_link = set_pop(attr_links)
 		dict_delete(model["type_mapping"], reverseKeyLookup(model["model"], read_edge_dst(model["model"][attr_link])))
 		dict_delete(model["type_mapping"], attr_link)
-		dict_delete(model["model"], reverseKeyLookup(model["model"], read_edge_dst(model["model"][attr_link])))
+		dict_delete_node(model["model"], reverseKeyLookup(model["model"], read_edge_dst(model["model"][attr_link])))
 		delete_element(model["model"][attr_link])
 
 	return!
@@ -452,26 +368,30 @@ Void function add_AL_links(model : Element, list : Element, element : Element, t
 	link_name = "__" + cast_id2s(link)
 
 	// The link
-	dict_add_fast(model["model"], link_name, link)
-	dict_add_fast(model["type_mapping"], link_name, (type + "_") + linkname)
+	dict_add(model["model"], link_name, link)
+	dict_add(model["type_mapping"], link_name, (type + "_") + linkname)
 
 	// The name link
 	link = read_out(link, 0)
 	link_name = "__" + cast_id2s(link)
 
-	dict_add_fast(model["model"], link_name, link)
-	dict_add_fast(model["type_mapping"], link_name, "dict_link_name")
-	
+	dict_add(model["model"], link_name, link)
+	dict_add(model["type_mapping"], link_name, "to_str")
+
 	// The name node
 	link = read_edge_dst(link)
 	link_name = "__" + cast_id2s(link)
 
 	if (bool_not(set_in_node(model["model"], link))):
-		dict_add_fast(model["model"], link_name, link)
-		dict_add_fast(model["type_mapping"], link_name, "StringAttr")
+		dict_add(model["model"], link_name, link)
+		dict_add(model["type_mapping"], link_name, "String")
 
 	// Now add the destination to the worker list
-	set_add(list, create_tuple(element[linkname], expected_type))
+	Element node
+	node = create_node()
+	list_append(node, element[linkname])
+	list_append(node, expected_type)
+	set_add(list, node)
 
 	return!
 
@@ -484,7 +404,10 @@ String function add_AL(model : Element, element : Element):
 	String elem_name
 
 	todo = create_node()
-	set_add(todo, create_tuple(element, "funcdef"))
+	node = create_node()
+	list_append(node, element)
+	list_append(node, "funcdef")
+	set_add(todo, node)
 
 	while (0 < dict_len(todo)):
 		work_node = set_pop(todo)
@@ -497,12 +420,12 @@ String function add_AL(model : Element, element : Element):
 				if (is_physical_action(elem)):
 					type = cast_a2s(elem)
 				else:
-					type = "Element"
+					type = "Any"
 
 			// Add the node itself
 			elem_name = "__" + cast_id2s(elem)
-			dict_add_fast(model["model"], elem_name, elem)
-			dict_add_fast(model["type_mapping"], elem_name, type)
+			dict_add(model["model"], elem_name, elem)
+			dict_add(model["type_mapping"], elem_name, type)
 
 			// Now add its edges
 			if (type == "if"):
@@ -515,7 +438,7 @@ String function add_AL(model : Element, element : Element):
 				add_AL_links(model, todo, elem, type, "body", "")
 				add_AL_links(model, todo, elem, type, "next", "")
 			elif (type == "assign"):
-				add_AL_links(model, todo, elem, type, "var", "resolve")
+				add_AL_links(model, todo, elem, type, "var", "")
 				add_AL_links(model, todo, elem, type, "value", "")
 				add_AL_links(model, todo, elem, type, "next", "")
 			elif (type == "break"):
@@ -527,7 +450,7 @@ String function add_AL(model : Element, element : Element):
 			elif (type == "resolve"):
 				add_AL_links(model, todo, elem, type, "var", "")
 			elif (type == "access"):
-				add_AL_links(model, todo, elem, type, "var", "resolve")
+				add_AL_links(model, todo, elem, type, "var", "")
 			elif (type == "constant"):
 				add_AL_links(model, todo, elem, type, "node", "")
 			elif (type == "output"):
@@ -542,8 +465,6 @@ String function add_AL(model : Element, element : Element):
 				add_AL_links(model, todo, elem, type, "next_param", "param")
 			elif (type == "funcdef"):
 				add_AL_links(model, todo, elem, type, "body", "")
-				// TODO this should be added, but is not the same as "param"
-				//add_AL_links(model, todo, elem, type, "params", "")
 				add_AL_links(model, todo, elem, type, "next", "")
 			elif (type == "call"):
 				add_AL_links(model, todo, elem, type, "func", "")
@@ -551,13 +472,80 @@ String function add_AL(model : Element, element : Element):
 				add_AL_links(model, todo, elem, type, "last_param", "param")
 				add_AL_links(model, todo, elem, type, "next", "")
 
-	// Mark the node as first
-	String initial
-	initial = instantiate_node(model, "Initial", "")
-	instantiate_link(model, "initial_funcdef", "", initial, reverseKeyLookup(model["model"], element))
-
 	return reverseKeyLookup(model["model"], element)!
 
+Void function add_constraint(model : Element, element : String, constraint : Action):
+	// Add local constraints to an element
+	Element attr_type
+	String link_name
+	String constraint_name
+
+	constraint_name = add_AL(model, constraint)
+	attr_type = find_attribute_type(model, element, "constraint")
+	instantiate_link(model, attr_type, "", element, constraint_name)
+
+	return!
+
+Void function construct_model():
+	String command
+
+	initialize_SCD("models/SimpleClassDiagrams")
+
+	while (True):
+		command = input()
+		if (command == "instantiate_bottom"):
+			Element m
+			m = instantiate_bottom()
+			dict_add(global_models, input(), m)
+		elif (command == "add_node"):
+			model_add_node(global_models[input()], input())
+		elif (command == "add_value"):
+			model_add_value(global_models[input()], input(), input())
+		elif (command == "add_edge"):
+			model_add_edge(global_models[input()], input(), input(), input())
+		elif (command == "exit"):
+			return!
+		elif (command == "retype_model"):
+			retype_model(global_models[input()], global_models[input()])
+		elif (command == "retype"):
+			retype(global_models[input()], input(), input())
+		elif (command == "instantiate_model"):
+			Element m
+			m = instantiate_model(global_models[input()])
+			dict_add(global_models, input(), m)
+		elif (command == "instantiate_node"):
+			instantiate_node(global_models[input()], input(), input())
+		elif (command == "instantiate_attribute"):
+			instantiate_attribute(global_models[input()], input(), input(), input())
+		elif (command == "instantiate_attribute_ref"):
+			instantiate_attribute_ref(global_models[input()], input(), input(), input())
+		elif (command == "instantiate_attribute_code"):
+			instantiate_attribute_code(global_models[input()], input(), input(), construct_function())
+		elif (command == "instantiate_link"):
+			instantiate_link(global_models[input()], input(), input(), input(), input())
+		elif (command == "add_constraint"):
+			add_constraint(global_models[input()], input(), construct_function())
+		elif (command == "initialize_SCD"):
+			initialize_SCD(input())
+		elif (command == "initialize_bottom"):
+			initialize_bottom(input())
+		elif (command == "export_node"):
+			String local_name
+			String location
+			local_name = input()
+			location = input()
+			export_node(location, global_models[local_name])
+		elif (command == "import_node"):
+			Element m
+			command = input()
+			m = import_node(command)
+			if (element_eq(m, read_root())):
+				log("Error: import not found for " + command)
+			else:
+				dict_add(global_models, input(), m)
+		else:
+			log("Modelling error: did not understand command " + command)
+
 Element function construct_model_raw(metamodel : Element):
 	String command
 	Element model
@@ -567,44 +555,42 @@ Element function construct_model_raw(metamodel : Element):
 	while (True):
 		command = input()
 		if (command == "add_node"):
+			input()
 			model_add_node(model, input())
 		elif (command == "add_value"):
+			input()
 			model_add_value(model, input(), input())
 		elif (command == "add_edge"):
+			input()
 			model_add_edge(model, input(), input(), input())
 		elif (command == "exit"):
 			return model!
 		elif (command == "instantiate_node"):
+			input()
 			instantiate_node(model, input(), input())
-		elif (command == "model_define_attribute"):
-			model_define_attribute(model, input(), input(), input(), input())
 		elif (command == "instantiate_attribute"):
+			input()
 			instantiate_attribute(model, input(), input(), input())
 		elif (command == "instantiate_attribute_ref"):
+			input()
 			instantiate_attribute_ref(model, input(), input(), input())
 		elif (command == "instantiate_attribute_code"):
+			input()
 			instantiate_attribute_code(model, input(), input(), construct_function())
 		elif (command == "instantiate_link"):
+			input()
 			instantiate_link(model, input(), input(), input(), input())
-		elif (command == "add_code_model"):
-			add_code_model(model, input(), construct_function())
+		elif (command == "add_constraint"):
+			input()
+			add_constraint(model, input(), construct_function())
+		elif (command == "import_node"):
+			input()
+			input()
+		elif (command == "export_node"):
+			input()
+			input()
+		elif (command == "instantiate_model"):
+			input()
+			input()
 		else:
 			log("Modelling error: did not understand command " + command)
-
-Element function get_func_AL_model(al_model : Element):
-	Element result
-	Element initial_function
-
-	// Find the initial function
-	initial_function = allInstances(al_model, "Initial")
-
-	if (read_nr_out(initial_function) == 0):
-		log("Could not find function to execute in this model!")
-		return create_node()!
-	elif (read_nr_out(initial_function) > 1):
-		log("Too many functions to execute in this model!")
-		return create_node()!
-	else:
-		initial_function = al_model["model"][set_pop(allAssociationDestinations(al_model, set_pop(initial_function), "initial_funcdef"))]
-
-	return initial_function!

+ 70 - 92
bootstrap/object_operations.alc

@@ -4,37 +4,36 @@ include "constructors.alh"
 include "modelling.alh"
 
 Element function allInstances(model : Element, type_name : String):
-	if (dict_in(model["metamodel"]["model"], type_name)):
-		Element result
-		Element accepted
-		Element keys
-		Element tm
-		String key
-		String class
-		Element results
-
-		result = create_node()
-		accepted = get_subclasses(model["metamodel"], type_name)
-
-		while (read_nr_out(accepted) > 0):
-			class = set_pop(accepted)
-			results = reverseKeyLookupMulti(model["type_mapping"], class)
-			set_merge(result, results)
-		return result!
-	else:
-		log("No such type in the metamodel: " + type_name)
-		return create_node()!
+	Element result
+	Element type
+
+	String key
+	Element keys
+
+	keys = dict_keys(model["model"])
+	type = model["metamodel"]["model"][type_name]
+	result = create_node()
+
+	while (0 < list_len(keys)):
+		key = set_pop(keys)
+		if (is_nominal_instance(model, key, type_name)):
+			set_add(result, key)
+
+	return result!
 
 Element function selectPossibleIncoming(model : Element, target : String, limit_set : Element):
 	// Find all possible incoming link types for the target model
 	// Should also include those specified on the superclass(es)
+
 	String type
 	Element model_dict
 	Element elem
 	Element result
 	Element target_element
+
 	result = create_node()
 	model_dict = model["model"]
+
 	while (0 < list_len(limit_set)):
 		type = set_pop(limit_set)
 		elem = model_dict[type]
@@ -65,42 +64,36 @@ Element function selectPossibleOutgoing(model : Element, source : String, limit_
 
 Element function allOutgoingAssociationInstances(model : Element, source_name : String, assoc_name : String):
 	// Read out all outgoing edges of the model and select those that are typed by the specified association
+	Element assocs
+	String assoc
 	Element result
 	Element source
-	String option
-	Integer all_out
-	Integer i
 
-	result = create_node()
+	assocs = allInstances(model, assoc_name)
 	source = model["model"][source_name]
-	all_out = read_nr_out(source)
-	i = 0
-	while (i < all_out):
-		option = reverseKeyLookup(model["model"], read_out(source, i))
-		if (is_nominal_instance(model, option, assoc_name)):
-			set_add(result, option)
-		i = i + 1
 
+	result = create_node()
+	while (0 < list_len(assocs)):
+		assoc = set_pop(assocs)
+		if (element_eq(source, read_edge_src(model["model"][assoc]))):
+			set_add(result, assoc)
 	return result!
 
 Element function allIncomingAssociationInstances(model : Element, target_name : String, assoc_name : String):
 	// Read out all outgoing edges of the model and select those that are typed by the specified association
+	Element assocs
+	String assoc
 	Element result
-	Element source
-	String option
-	Integer all_out
-	Integer i
+	Element target
 
-	result = create_node()
-	source = model["model"][target_name]
-	all_out = read_nr_in(source)
-	i = 0
-	while (i < all_out):
-		option = reverseKeyLookup(model["model"], read_in(source, i))
-		if (is_nominal_instance(model, option, assoc_name)):
-			set_add(result, option)
-		i = i + 1
+	assocs = allInstances(model, assoc_name)
+	target = model["model"][target_name]
 
+	result = create_node()
+	while (0 < list_len(assocs)):
+		assoc = set_pop(assocs)
+		if (element_eq(target, read_edge_dst(model["model"][assoc]))):
+			set_add(result, assoc)
 	return result!
 
 Element function getAttributeList(model : Element, element : String):
@@ -109,44 +102,50 @@ Element function getAttributeList(model : Element, element : String):
 	Element type
 	Element attr_name
 	Element types
-	Element mm
 	String attr_type
 
 	result = create_node()
-	mm = model["metamodel"]["model"]
 	types = get_superclasses(model["metamodel"], read_type(model, element))
 
 	while (read_nr_out(types) > 0):
 		type = set_pop(types)
+		keys = dict_keys(model["metamodel"]["model"][type])
 
 		// Add our own attributes
-		keys = dict_keys(mm[type])
-		while (read_nr_out(keys) > 0):
+		while (0 < list_len(keys)):
 			attr_name = set_pop(keys)
 			if (is_physical_string(attr_name)):
-				attr_type = reverseKeyLookup(mm, mm[type][attr_name])
-				// WARNING: do not change this to dict_add_fast, as this crashes random code...
+				attr_type = reverseKeyLookup(model["metamodel"]["model"], model["metamodel"]["model"][type][attr_name])
 				dict_add(result, attr_name, attr_type)
 
 	return result!
 
 Element function getInstantiatableAttributes(model : Element, element : String):
-	Element all_links
 	Element result
-	String link
-
 	result = create_node()
 
-	all_links = allOutgoingAssociationInstances(model, element, "Attribute")
-	while (read_nr_out(all_links) > 0):
-		link = set_pop(all_links)
-		// WARNING: do not change this to dict_add_fast, as this crashes random code...
-		dict_add(result, read_attribute(model, link, "name"), read_type(model, readAssociationDestination(model, link)))
+	Element types
+	types = get_superclasses(model, element)
+
+	while (read_nr_out(types) > 0):
+		element = set_pop(types)
+
+		// Get all outgoing "dictionary" links
+		Element set_own
+		Element elem
+		elem = model["model"][element]
+		set_own = dict_keys(elem)
+
+		// Filter them
+		Element e
+		while (0 < read_nr_out(set_own)):
+			e = set_pop(set_own)
+			if (is_physical_string(e)):
+				dict_add(result, e, reverseKeyLookup(model["model"], elem[e]))
 
 	return result!
 
 String function reverseKeyLookup(dict : Element, element : Element):
-	// TODO don't know if this AL will actually work...
 	Integer nr_in
 	Integer nr_out
 	Integer counter
@@ -162,27 +161,7 @@ String function reverseKeyLookup(dict : Element, element : Element):
 		counter = counter + 1
 	
 	return string_join(string_join("(unknown: ", cast_e2s(element)), " )")!
-
-Element function reverseKeyLookupMulti(dict : Element, element : Element):
-	// TODO don't know if this AL will actually work...
-	Integer nr_in
-	Integer nr_out
-	Integer counter
-	Element link
-	Element result
-
-	result = create_node()
-	nr_in = read_nr_in(element)
-	counter = 0
-	while (counter < nr_in):
-		if (element_eq(read_edge_src(read_in(element, counter)), dict)):
-			// Got a match
-			set_add(result, read_edge_dst(read_out(read_in(element, counter), 0)))
-
-		counter = counter + 1
 	
-	return result!
-
 String function print_dict(dict : Element):
 	Element keys
 	Element key
@@ -204,27 +183,27 @@ String function readAssociationSource(model : Element, name : String):
 String function readAssociationDestination(model : Element, name : String):
 	return reverseKeyLookup(model["model"], read_edge_dst(model["model"][name]))!
 
-Element function allAssociationDestinations(model : Element, name : String, association_type : String):
-	Element tmp
+String function followAssociation(model : Element, element_name : String, association_name : String):
+	Element assocs
+	String assoc
 	Element result
 
+	assocs = allOutgoingAssociationInstances(model, element_name, association_name)
 	result = create_node()
-	tmp = allOutgoingAssociationInstances(model, name, association_type)
-
-	while (read_nr_out(tmp) > 0):
-		set_add(result, readAssociationDestination(model, set_pop(tmp)))
+	while (0 < list_len(assocs)):
+		set_add(result, readAssociationDestination(model, set_pop(assocs)))
 
 	return result!
 
-Element function allAssociationOrigins(model : Element, name : String, association_type : String):
+Element function allAssociationDestinations(model : Element, name : String, association_type : String):
 	Element tmp
 	Element result
 
 	result = create_node()
-	tmp = allIncomingAssociationInstances(model, name, association_type)
+	tmp = allOutgoingAssociationInstances(model, name, association_type)
 
 	while (read_nr_out(tmp) > 0):
-		set_add(result, readAssociationSource(model, set_pop(tmp)))
+		set_add(result, readAssociationDestination(model, set_pop(tmp)))
 
 	return result!
 
@@ -257,9 +236,7 @@ Element function allowedAssociationsBetween(model : Element, src : String, dst :
 
 				if (is_nominal_instance(model, dst, dst_name)):
 					// Find out whether our dst is an instance of the found destination type
-
-					if (is_nominal_instance(model["metamodel"], edge_name, "Association")):
-						set_add(result, edge_name)
+					set_add(result, edge_name)
 
 			i = i + 1
 
@@ -281,7 +258,8 @@ String function read_type(model : Element, name : String):
 				return ""!
 		else:
 			log("Untyped " + name)
+			log("Type mapping: " + dict_to_string(model["type_mapping"]))
 			return ""!
 	else:
-		log("Couldn't find type of " + name)
+		log("Couldn't find " + name)
 		return ""!

+ 0 - 53
bootstrap/pm.mvc

@@ -1,53 +0,0 @@
-import models/SimpleClassDiagrams as SimpleClassDiagrams
-include "primitives.alh"
-include "object_operations.alh"
-
-SimpleClassDiagrams ProcessModel {
-    SimpleAttribute String {}
-    SimpleAttribute MvCName {
-        constraint = $
-            String function constraint(model : Element, name : String):
-                if (bool_not(is_physical_string(model["model"][name]))):
-                    return "MvCName has no string value"!
-                else:
-                    return "OK"!
-            $
-    }
-
-    Class Activity {}
-    Class Start : Activity {
-        lower_cardinality = 1
-        upper_cardinality = 1
-    }
-    Class Finish : Activity {
-        lower_cardinality = 1
-    }
-    Class Fork : Activity {}
-    Class Join : Activity {}
-    Class Decision : Activity {
-        constraint = $
-            String function constraint(model : Element, name : String):
-                if (read_nr_out(allOutgoingAssociationInstances(model, name, "Next")) == 0):
-                    return "OK"!
-                else:
-                    return "Decision node cannot have a normal 'Next' link"!
-            $
-    }
-
-    Class Exec : Activity {
-        name : MvCName
-    }
-
-    Class Data {
-        name : MvCName
-        type : MvCName
-    }
-
-    Association Produces (Exec, Data) {}
-    Association Consumes (Exec, Data) {}
-    Association Then (Decision, Activity) {}
-    Association Else (Decision, Activity) {}
-    Association Next (Activity, Activity) {}
-}
-
-export ProcessModel to models/ProcessModel

+ 6 - 55
bootstrap/primitives.alc

@@ -33,7 +33,6 @@ String function cast_a2s(a: Action) = ?primitives/cast_a2s
 String function cast_v2s(a: Element) = ?primitives/cast_v2s
 String function cast_id2s(a: Element) = ?primitives/cast_id2s
 Element function dict_add(a: Element, b: Element, c: Element) = ?primitives/dict_add
-Element function dict_add_fast(a: Element, b: Element, c: Element) = ?primitives/dict_add_fast
 Element function dict_delete(a: Element, b: Element) = ?primitives/dict_delete
 Element function dict_delete_node(a: Element, b: Element) = ?primitives/dict_delete_node
 Element function dict_read(a: Element, b: Element) = ?primitives/dict_read
@@ -72,6 +71,7 @@ String function string_join(a: String, b: String) = ?primitives/string_join
 String function string_get(a: String, b: Integer) = ?primitives/string_get
 Element function string_split(a: String, b: String) = ?primitives/string_split
 Integer function string_len(a: String) = ?primitives/string_len
+Element function deserialize(a: String) = ?primitives/deserialize
 Element function log(a: String) = ?primitives/log
 Element function read_root() = ?primitives/read_root
 Element function read_taskroot() = ?primitives/read_taskroot
@@ -241,11 +241,10 @@ String function dict_to_string(d : Element):
 	Element key
 
 	result = "{"
-
 	keys = dict_keys(d)
-	while (read_nr_out(keys) > 0):
-		key = set_pop(keys)
 
+	while (read_nr_out(keys)):
+		key = set_pop(keys)
 		result = result + cast_v2s(key)
 		result = result + ": "
 		result = result + cast_v2s(dict_read_node(d, key))
@@ -293,33 +292,17 @@ Boolean function set_equality(sa : Element, sb : Element):
 	
 	return True!
 
-Boolean function dict_eq(da : Element, db : Element):
-	if (bool_not(set_equality(dict_keys(da), dict_keys(db)))):
-		// They don't even share the same keys
-		return False!
-
-	Element keys
-	Element key
-	keys = dict_keys(da)
-	while (read_nr_out(keys) > 0):
-		key = set_pop(keys)
-		if (value_neq(da[key], db[key])):
-			// Value that is not equal
-			return False!
-
-	return True!
-
 Element function dict_copy(d : Element):
 	String result
 	Element keys
 	Element key
 
 	result = create_node()
-
 	keys = dict_keys(d)
-	while (read_nr_out(keys) > 0):
+
+	while (read_nr_out(keys)):
 		key = set_pop(keys)
-		dict_add_fast(result, key, dict_read_node(d, key))
+		dict_add(result, key, dict_read_node(d, key))
 
 	return result!
 
@@ -333,35 +316,3 @@ Element function set_to_list(s : Element):
 		list_append(result, set_pop(tmp))
 
 	return result!
-
-Void function dict_overwrite(d : Element, key : Element, value : Element):
-	if (dict_in(d, key)):
-		dict_delete(d, key)
-	if (dict_in_node(d, key)):
-		dict_delete_node(d, key)
-	dict_add(d, key, value)
-
-	return !
-
-Element function set_merge(a : Element, b : Element):
-	b = set_copy(b)
-	while (read_nr_out(b) > 0):
-		set_add(a, set_pop(b))
-	return a!
-
-Element function make_reverse_dictionary(dict : Element):
-	Element keys
-	Element reverse
-	String key
-	String value
-
-	reverse = create_node()
-	keys = dict_keys(dict)
-	while (read_nr_out(keys) > 0):
-		key = set_pop(keys)
-		value = cast_id2s(dict[key])
-		if (dict_in(reverse, value)):
-			dict_delete(reverse, value)
-		dict_add(reverse, value, key)
-
-	return reverse!

+ 106 - 119
bootstrap/ramify.alc

@@ -3,18 +3,17 @@ include "object_operations.alh"
 include "modelling.alh"
 include "metamodels.alh"
 include "model_management.alh"
-include "conformance_scd.alh"
 
 Element function ramify(model : Element):
 	// Create new model structure
 	Element new_model
 	new_model = create_node()
-	dict_add_fast(new_model, "model", create_node())
-	dict_add_fast(new_model, "type_mapping", create_node())
-	dict_add_fast(new_model, "metamodel", model["metamodel"])
+	dict_add(new_model, "model", create_node())
+	dict_add(new_model, "type_mapping", create_node())
+	dict_add(new_model, "metamodel", model["metamodel"])
 
-	dict_add_fast(new_model, "source", model)
-	dict_add_fast(new_model, "target", model)
+	dict_add(new_model, "source", model)
+	dict_add(new_model, "target", model)
 
 	// Get local variables for parts
 	Element old_m
@@ -25,32 +24,27 @@ Element function ramify(model : Element):
 	mm = new_model["metamodel"]["model"]
 
 	// Add in some primitives
-	instantiate_node(new_model, "SimpleAttribute", "Natural")
-	instantiate_attribute(new_model, "Natural", "constraint", constraint_Natural)
+	instantiate_node(new_model, "Class", "Natural")
+	instantiate_node(new_model, "Class", "String")
+	instantiate_node(new_model, "Class", "Any")
 
-	instantiate_node(new_model, "SimpleAttribute", "String")
-	instantiate_attribute(new_model, "String", "constraint", constraint_String)
-
-	instantiate_node(new_model, "SimpleAttribute", "Boolean")
-	instantiate_attribute(new_model, "Boolean", "constraint", constraint_Boolean)
-
-	instantiate_node(new_model, "SimpleAttribute", "Location")
-	instantiate_attribute(new_model, "Location", "constraint", constraint_Location)
-
-	instantiate_node(new_model, "ComplexAttribute", "ActionLanguage")
-	instantiate_attribute(new_model, "ActionLanguage", "constraint", constraint_ActionLanguage)
-	model_define_attribute(new_model, "ActionLanguage", "type", False, "Location")
+	// Add in the complete AL metamodel
+	add_AL_to_MM(new_model)
 
 	// Add some default elements
 	//	Class LHS_Root {
-	//		constraint? : ActionLanguage
+	//		constraint : funcdef {
+	//			target_upper_cardinality = 1
+	//		}
 	//		upper_cardinality = 1
 	//		lower_cardinality = 1
 	//	}
 	instantiate_node(new_model, "Class", "LHS_Root")
 	instantiate_attribute(new_model, "LHS_Root", "lower_cardinality", 1)
 	instantiate_attribute(new_model, "LHS_Root", "upper_cardinality", 1)
-	model_define_attribute(new_model, "LHS_Root", "constraint", True, "ActionLanguage")
+	instantiate_link(new_model, "Association", "LHS_constraint", "LHS_Root", "funcdef")
+	instantiate_attribute(new_model, "LHS_constraint", "name", "constraint")
+	instantiate_attribute(new_model, "LHS_constraint", "target_upper_cardinality", 1)
 
 	//  Class LHS : LHS_Root {}
 	instantiate_node(new_model, "Class", "LHS")
@@ -60,37 +54,69 @@ Element function ramify(model : Element):
 	instantiate_node(new_model, "Class", "NAC")
 	instantiate_link(new_model, "Inheritance", "", "NAC", "LHS_Root")
 
-	//	Class PreElement {
-	//		label : String
-	//		constraint? : ActionLanguage
+	//	Class Pre_Element {
+	//		label : String {
+	//			target_lower_cardinality = 1
+	//			target_upper_cardinality = 1
+	//		}
+	//		constraint : funcdef {
+	//			target_upper_cardinality = 1
+	//		}
 	//	}
-	instantiate_node(new_model, "Class", "PreElement")
-	model_define_attribute(new_model, "PreElement", "label", False, "String")
-	model_define_attribute(new_model, "PreElement", "constraint", True, "ActionLanguage")
-
-	// Association LHS_contains (LHS_Root, PreElement) {}
-	instantiate_link(new_model, "Association", "LHS_contains", "LHS_Root", "PreElement")
+	instantiate_node(new_model, "Class", "Pre_Element")
+	instantiate_link(new_model, "Association", "Pre_Element_label", "Pre_Element", "String")
+	instantiate_attribute(new_model, "Pre_Element_label", "name", "label")
+	instantiate_attribute(new_model, "Pre_Element_label", "target_lower_cardinality", 1)
+	instantiate_attribute(new_model, "Pre_Element_label", "target_upper_cardinality", 1)
+	instantiate_link(new_model, "Association", "Pre_Element_constraint", "Pre_Element", "funcdef")
+	instantiate_attribute(new_model, "Pre_Element_constraint", "name", "constraint")
+	instantiate_attribute(new_model, "Pre_Element_constraint", "target_upper_cardinality", 1)
+
+	// Association LHS_contains (LHS_Root, Pre_Element) {}
+	instantiate_link(new_model, "Association", "LHS_contains", "LHS_Root", "Pre_Element")
+	instantiate_attribute(new_model, "LHS_contains", "name", "contains")
 
 	//	Class RHS {
-	//		action? : ActionLanguage
+	//		action : FuncDef {
+	//			target_upper_cardinality = 1
+	//		}
 	//		upper_cardinality = 1
 	//		lower_cardinality = 1
 	//	}
 	instantiate_node(new_model, "Class", "RHS")
 	instantiate_attribute(new_model, "RHS", "lower_cardinality", 1)
 	instantiate_attribute(new_model, "RHS", "upper_cardinality", 1)
-	model_define_attribute(new_model, "RHS", "action", True, "ActionLanguage")
-
-	//	Class PostElement {
-	//		label : String
-	//		action? : ActionLanguage
+	instantiate_link(new_model, "Association", "RHS_action", "RHS", "funcdef")
+	instantiate_attribute(new_model, "RHS_action", "name", "action")
+	instantiate_attribute(new_model, "RHS_action", "target_upper_cardinality", 1)
+
+	//	Class Post_Element {
+	//		label : String {
+	//			target_lower_cardinality = 1
+	//			target_upper_cardinality = 1
+	//		}
+	//		value : funcdef {
+	//			target_upper_cardinality = 1
+	//		}
+	//		action : funcdef {
+	//			target_upper_cardinality = 1
+	//		}
 	//	}
-	instantiate_node(new_model, "Class", "PostElement")
-	model_define_attribute(new_model, "PostElement", "label", False, "String")
-	model_define_attribute(new_model, "PostElement", "action", True, "ActionLanguage")
-
-	// Association RHS_contains (RHS, PostElement) {}
-	instantiate_link(new_model, "Association", "RHS_contains", "RHS", "PostElement")
+	instantiate_node(new_model, "Class", "Post_Element")
+	instantiate_link(new_model, "Association", "Post_Element_label", "Post_Element", "String")
+	instantiate_attribute(new_model, "Post_Element_label", "name", "label")
+	instantiate_attribute(new_model, "Post_Element_label", "target_lower_cardinality", 1)
+	instantiate_attribute(new_model, "Post_Element_label", "target_upper_cardinality", 1)
+	instantiate_link(new_model, "Association", "Post_Element_value", "Post_Element", "funcdef")
+	instantiate_attribute(new_model, "Post_Element_value", "name", "value")
+	instantiate_attribute(new_model, "Post_Element_value", "target_upper_cardinality", 1)
+	instantiate_link(new_model, "Association", "Post_Element_action", "Post_Element", "funcdef")
+	instantiate_attribute(new_model, "Post_Element_action", "name", "action")
+	instantiate_attribute(new_model, "Post_Element_action", "target_upper_cardinality", 1)
+
+	// Association RHS_contains (RHS, Post_Element) {}
+	instantiate_link(new_model, "Association", "RHS_contains", "RHS", "Post_Element")
+	instantiate_attribute(new_model, "RHS_contains", "name", "contains")
 
 	// Basics are added, now we need to add each node and transition, but slightly modified
 	Element keys
@@ -98,30 +124,15 @@ Element function ramify(model : Element):
 	Element new_entry
 	Element entry
 
-	keys = set_to_list(dict_keys(old_m))
+	keys = dict_keys(old_m)
 	String type_name
 	String old_source
 	String old_target
-	String attr_name
-	Element masked_attributes
-	Element copied_attributes
-
-	Integer i
-	Integer cnt
-
-	masked_attributes = create_node()
-	set_add(masked_attributes, "constraint")
-	set_add(masked_attributes, "lower_cardinality")
-	set_add(masked_attributes, "source_lower_cardinality")
-	set_add(masked_attributes, "target_lower_cardinality")
-
-	copied_attributes = create_node()
-	set_add(copied_attributes, "upper_cardinality")
-	set_add(copied_attributes, "source_upper_cardinality")
-	set_add(copied_attributes, "target_upper_cardinality")
+	Element to_link
+	to_link = create_node()
 
 	while (read_nr_out(keys) > 0):
-		key = list_pop(keys, 0)
+		key = set_pop(keys)
 		entry = old_m[key]
 
 		type_name = read_type(model, key)
@@ -130,72 +141,48 @@ Element function ramify(model : Element):
 			instantiate_node(new_model, type_name, "Post_" + key)
 
 			// Also make it inherit from the "root element"
-			instantiate_link(new_model, "Inheritance", "", "Pre_" + key, "PreElement")
-			instantiate_link(new_model, "Inheritance", "", "Post_" + key, "PostElement")
-
-			i = 0
-			cnt = read_nr_out(copied_attributes)
-			while (i < cnt):
-				attr_name = read_edge_dst(read_out(copied_attributes, i))
-				if (element_neq(read_attribute(model, key, attr_name), read_root())):
-					// Attribute was defined, so reassign in both LHS and RHS
-					instantiate_attribute(new_model, "Pre_" + key, attr_name, read_attribute(model, key, attr_name))
-					instantiate_attribute(new_model, "Post_" + key, attr_name, read_attribute(model, key, attr_name))
-				i = i + 1
-
-		elif (type_name == "AttributeLink"):
-			// Got an attribute, so find out the source and name
-			old_source = reverseKeyLookup(model["model"], read_edge_src(entry))
-			attr_name = read_attribute(model, key, "name")
-
-			// TODO distinguish between Simple and Complex Attributes
-
-			if (dict_in(new_model["model"], "Pre_" + old_source)):
-				// Only if it is a class that it originates from is a class, should we add this
-				if (is_nominal_instance(model, old_source, "Element")):
-					// If the attribute is one used in the conformance check, we should mask it
-					// Add the attribute in the new model, altering its name and making it optional
-					model_define_attribute(new_model, "Pre_" + old_source, "constraint_" + attr_name, True, "ActionLanguage")
-					model_define_attribute(new_model, "Post_" + old_source, "value_" + attr_name, True, "ActionLanguage")
-			else:
-				// Queue for later
-				list_append(keys, key)
+			instantiate_link(new_model, "Inheritance", "", "Pre_" + key, "Pre_Element")
+			instantiate_link(new_model, "Inheritance", "", "Post_" + key, "Post_Element")
 
 		elif (type_name == "Association"):
 			old_source = reverseKeyLookup(model["model"], read_edge_src(entry))
 			old_target = reverseKeyLookup(model["model"], read_edge_dst(entry))
+			instantiate_link(new_model, type_name, "Pre_" + key, "Pre_" + old_source, "Pre_" + old_target)
+			instantiate_link(new_model, type_name, "Post_" + key, "Post_" + old_source, "Post_" + old_target)
 
-			if (bool_and(dict_in(new_model["model"], "Pre_" + old_source), dict_in(new_model["model"], "Pre_" + old_target))):
-				instantiate_link(new_model, type_name, "Pre_" + key, "Pre_" + old_source, "Pre_" + old_target)
-				instantiate_link(new_model, type_name, "Post_" + key, "Post_" + old_source, "Post_" + old_target)
-
-				// Make it inherit from the Root Element (PreElement or PostElement)
-				instantiate_link(new_model, "Inheritance", "", "Pre_" + key, "PreElement")
-				instantiate_link(new_model, "Inheritance", "", "Post_" + key, "PostElement")
-			else:
-				// Queue for later
-				list_append(keys, key)
-				
-			i = 0
-			cnt = read_nr_out(copied_attributes)
-			while (i < cnt):
-				attr_name = read_edge_dst(read_out(copied_attributes, i))
-				if (element_neq(read_attribute(model, key, attr_name), read_root())):
-					// Attribute was defined, so reassign in both LHS and RHS
-					instantiate_attribute(new_model, "Pre_" + key, attr_name, read_attribute(model, key, attr_name))
-					instantiate_attribute(new_model, "Post_" + key, attr_name, read_attribute(model, key, attr_name))
-				i = i + 1
-
+			// 1) Make it inherit from the Root Element (Pre_Element or Post_Element)
+			instantiate_link(new_model, "Inheritance", "", "Pre_" + key, "Pre_Element")
+			instantiate_link(new_model, "Inheritance", "", "Post_" + key, "Post_Element")
+			
 		elif (type_name == "Inheritance"):
 			old_source = reverseKeyLookup(model["model"], read_edge_src(entry))
 			old_target = reverseKeyLookup(model["model"], read_edge_dst(entry))
-
-			if (bool_and(dict_in(new_model["model"], "Pre_" + old_source), dict_in(new_model["model"], "Pre_" + old_target))):
-				instantiate_link(new_model, type_name, "Pre_" + key, "Pre_" + old_source, "Pre_" + old_target)
-				instantiate_link(new_model, type_name, "Post_" + key, "Post_" + old_source, "Post_" + old_target)
+			instantiate_link(new_model, type_name, "Pre_" + key, "Pre_" + old_source, "Pre_" + old_target)
+			instantiate_link(new_model, type_name, "Post_" + key, "Post_" + old_source, "Post_" + old_target)
+
+		elif (bool_not(has_value(entry))):
+			create_edge(to_link, entry)
+
+	while (read_nr_out(to_link) > 0):
+		entry = set_pop(to_link)
+		type_name = read_type(model, reverseKeyLookup(model["model"], entry))
+		// Primitive values themselves are not copied, so skip that here
+
+		// An instance link, so just copy over (don't make element of Root Element), and don't even copy if it is lower cardinality
+		// It is probably an attribute at the meta-language level, so check which one it is
+		String name
+		name = read_attribute(model["metamodel"], type_name, "name")
+		if (bool_not(bool_or(bool_or(name == "lower_cardinality", name == "source_lower_cardinality"), bool_or(name == "constraint", name == "target_lower_cardinality")))):
+			// Not a lower cardinality or constraint, so copy
+			old_source = reverseKeyLookup(model["model"], read_edge_src(entry))
+			if (bool_or(bool_or(name == "name", name == "upper_cardinality"), bool_or(name == "source_upper_cardinality", name == "target_upper_cardinality"))):
+				// Keep the old name for the physical attributes!
+				instantiate_attribute(new_model, "Pre_" + old_source, name, read_edge_dst(entry))
+				instantiate_attribute(new_model, "Post_" + old_source, name, read_edge_dst(entry))
 			else:
-				// Queue for later
-				list_append(keys, key)
+				// Rename the attributes as well
+				instantiate_attribute(new_model, "Pre_" + old_source, "Pre_" + name, read_edge_dst(entry))
+				instantiate_attribute(new_model, "Post_" + old_source, "Post_" + name, read_edge_dst(entry))
 
 	// Define schedule over these elements
 

+ 27 - 0
bootstrap/task_interface.alc

@@ -0,0 +1,27 @@
+// Do this only in the bootstrapper
+include "io.alh"
+include "primitives.alh"
+include "compilation_manager.alh"
+include "constructors.alh"
+include "modelling.alh"
+
+Void mutable function new_task():
+	Integer interface
+	while (True):
+		interface = input()
+		if (interface == 0):
+			exec(deserialize(input()))
+		elif (interface == 1):
+			exec(construct_unknown())
+		elif (interface == 2):
+			output("DONE")
+		elif (interface == 3):
+			compilation_manager()
+		elif (interface == 4):
+			construct_model()
+		elif (interface == -1):
+			return!
+		else:
+			log("Unsupported interface!")
+
+	return!

+ 12 - 18
bootstrap/task_manager.alc

@@ -1,7 +1,5 @@
 include "io.alh"
 include "primitives.alh"
-include "metamodels.alh"
-include "core_algorithm.alh"
 
 Void function task_management():
 	String taskname
@@ -9,10 +7,6 @@ Void function task_management():
 	Element task_frame
 	Element output_value
 	Element input_value
-
-	// Initialize the basic formalisms before allowing new users
-	initialize_MMs()
-	initialize_core()
 	
 	while (True):
 		taskname = input()
@@ -21,18 +15,18 @@ Void function task_management():
 			task_frame = create_node()
 			output_value = create_node()
 			input_value = create_node()
-			dict_add_fast(task_root, "frame", task_frame)
-			dict_add_fast(task_root, "globals", create_node())
-			dict_add_fast(task_root, "output", output_value)
-			dict_add_fast(task_root, "last_output", output_value)
-			dict_add_fast(task_root, "input", input_value)
-			dict_add_fast(task_root, "last_input", input_value)
-			dict_add_fast(task_frame, "evalstack", create_node())
-			dict_add_fast(task_frame, "returnvalue", create_node())
-			dict_add_fast(task_frame, "phase", "init")
-			dict_add_fast(task_frame, "IP", dict_read(dict_read(read_root(), "__hierarchy"), "__IP"))
-			dict_add_fast(task_frame, "symbols", create_node())
+			dict_add(task_root, "frame", task_frame)
+			dict_add(task_root, "globals", create_node())
+			dict_add(task_root, "output", output_value)
+			dict_add(task_root, "last_output", output_value)
+			dict_add(task_root, "input", input_value)
+			dict_add(task_root, "last_input", input_value)
+			dict_add(task_frame, "evalstack", create_node())
+			dict_add(task_frame, "returnvalue", create_node())
+			dict_add(task_frame, "phase", "init")
+			dict_add(task_frame, "IP", dict_read(dict_read(read_root(), "__hierarchy"), "__IP"))
+			dict_add(task_frame, "symbols", create_node())
 
 			//Add this only at the end, as otherwise the task will already be detected
-			dict_add_fast(read_root(), taskname, task_root)
+			dict_add(read_root(), taskname, task_root)
 	return!

+ 0 - 15
bootstrap/tracability.mvc

@@ -1,15 +0,0 @@
-import models/SimpleClassDiagrams as SimpleClassDiagrams
-
-include "primitives.alh"
-include "object_operations.alh"
-
-SimpleClassDiagrams Tracability {
-    SimpleAttribute String {}
-
-    Class Reference {}
-    Association TracabilityLink {
-        type : String
-    }
-}
-
-export Tracability to models/Tracability

+ 58 - 175
bootstrap/transform.alc

@@ -4,7 +4,6 @@ include "modelling.alh"
 include "random.alh"
 include "conformance_scd.alh"
 include "model_management.alh"
-include "library.alh"
 
 Element function make_matching_schedule(schedule_model : Element, LHS : String, ignore : Element):
 	Element schedule
@@ -17,9 +16,6 @@ Element function make_matching_schedule(schedule_model : Element, LHS : String,
 	String next
 	Element tmp
 
-	Element reverse
-	reverse = make_reverse_dictionary(schedule_model["model"])
-
 	// Initialize
 	schedule = create_node()
 	workset = create_node()
@@ -47,30 +43,21 @@ Element function make_matching_schedule(schedule_model : Element, LHS : String,
 			if (bool_not(set_in(schedule, next))):
 				if (set_in(full_all_elements, next)):
 					if (bool_not(set_in(ignore, read_attribute(schedule_model, next, "label")))):
-						list_insert(schedule, next, 0)
-					else:
+						list_append(schedule, next)
 						required_size = required_size - 1
-						continue!
 
 					// If it is an edge, we should also add the target and source
 					if (is_edge(schedule_model["model"][next])):
 						// Add the target/source to the schedule
-						set_add(workset, reverse[cast_id2s(read_edge_src(schedule_model["model"][next]))])
-						set_add(workset, reverse[cast_id2s(read_edge_dst(schedule_model["model"][next]))])
+						set_add(workset, reverseKeyLookup(schedule_model["model"], read_edge_src(schedule_model["model"][next])))
+						set_add(workset, reverseKeyLookup(schedule_model["model"], read_edge_dst(schedule_model["model"][next])))
 
 					// Also add all outgoing links
 					counter = read_nr_out(schedule_model["model"][next])
 					while (counter > 0):
 						counter = counter - 1
 						if (set_in_node(schedule_model["model"], read_out(schedule_model["model"][next], counter))):
-							set_add(workset, reverse[cast_id2s(read_out(schedule_model["model"][next], counter))])
-
-					// And incoming links
-					counter = read_nr_in(schedule_model["model"][next])
-					while (counter > 0):
-						counter = counter - 1
-						if (set_in_node(schedule_model["model"], read_in(schedule_model["model"][next], counter))):
-							set_add(workset, reverse[cast_id2s(read_in(schedule_model["model"][next], counter))])
+							set_add(workset, reverseKeyLookup(schedule_model["model"], read_out(schedule_model["model"][next], counter)))
 
 	return schedule!
 
@@ -80,74 +67,59 @@ Element function get_possible_bindings(host_model : Element, schedule_model : El
 	String dst_label
 	String typename
 	String original_typename
-	Boolean guaranteed_instance
 
 	options = create_node()
 
 	typename = read_type(schedule_model, current_element)
 	original_typename = string_substr(typename, 4, string_len(typename))
-	guaranteed_instance = False
-	
+
 	if (is_edge(schedule_model["model"][current_element])):
-		Boolean src_in
-		Boolean dst_in
 		// Is an edge, so check for already bound source/target
 		src_label = read_attribute(schedule_model, reverseKeyLookup(schedule_model["model"], read_edge_src(schedule_model["model"][current_element])), "label")
 		dst_label = read_attribute(schedule_model, reverseKeyLookup(schedule_model["model"], read_edge_dst(schedule_model["model"][current_element])), "label")
-		src_in = set_in(dict_keys(map), src_label)
-		dst_in = set_in(dict_keys(map), dst_label)
-
-		guaranteed_instance = True
 
-		if (bool_and(src_in, dst_in)):
+		if (bool_and(set_in(dict_keys(map), src_label), set_in(dict_keys(map), dst_label))):
 			// Source and destination are bound
 			options = allOutgoingAssociationInstances(host_model, map[src_label], original_typename)
-			if (read_nr_out(options) > 0):
-				options = set_overlap(options, allIncomingAssociationInstances(host_model, map[dst_label], original_typename))
+			options = set_overlap(options, allIncomingAssociationInstances(host_model, map[dst_label], original_typename))
 
-		elif (src_in):
+		elif (set_in(dict_keys(map), src_label)):
 			// Source is bound
 			options = allOutgoingAssociationInstances(host_model, map[src_label], original_typename)
 
-		elif (dst_in):
+		elif (set_in(dict_keys(map), dst_label)):
 			// Destination is bound
 			options = allIncomingAssociationInstances(host_model, map[dst_label], original_typename)
 
 		else:
 			// Neither is bound, so just get all of them
-			options = allInstances(host_model, original_typename)
+			log("ERROR: unbound source/target for association!")
+			//TODO should actually return all
+			return create_node()!
 	else:
 		// Is a node, so find whether or not there are some connections that are already resolved
 		Element ic
 		Element oc
 		String poll
-		String value
 
-		oc = allOutgoingAssociationInstances(schedule_model, current_element, "PreElement")
-		while (bool_and(read_nr_out(oc) > 0, read_nr_out(options) < 2)):
-			poll = set_pop(oc)
+		ic = allIncomingAssociationInstances(schedule_model, current_element, "Pre_Element")
+		oc = allOutgoingAssociationInstances(schedule_model, current_element, "Pre_Element")
+
+		while (bool_and(read_nr_out(ic) > 0, read_nr_out(options) == 0)):
+			poll = set_pop(ic)
 			if (dict_in(map, read_attribute(schedule_model, poll, "label"))):
 				// This incoming link is already defined, so we just have one option: the destination of the link we matched
-				value = readAssociationSource(host_model, map[read_attribute(schedule_model, poll, "label")])
-				if (bool_not(set_in(options, value))):
-					set_add(options, value)
-
-		if (read_nr_out(options) < 2):
-			ic = allIncomingAssociationInstances(schedule_model, current_element, "PreElement")
-			String value
-			while (bool_and(read_nr_out(ic) > 0, read_nr_out(options) < 2)):
-				poll = set_pop(ic)
-				if (dict_in(map, read_attribute(schedule_model, poll, "label"))):
-					// This incoming link is already defined, so we just have one option: the destination of the link we matched
-					value = readAssociationDestination(host_model, map[read_attribute(schedule_model, poll, "label")])
-					if (bool_not(set_in(options, value))):
-						set_add(options, value)
+				set_add(options, readAssociationDestination(host_model, map[read_attribute(schedule_model, poll, "label")]))
 			
+		while (bool_and(read_nr_out(oc) > 0, read_nr_out(options) == 0)):
+			poll = set_pop(oc)
+			if (dict_in(map, read_attribute(schedule_model, poll, "label"))):
+				// This incoming link is already defined, so we just have one option: the destination of the link we matched
+				set_add(options, readAssociationSource(host_model, map[read_attribute(schedule_model, poll, "label")]))
+
 		if (read_nr_out(options) == 0):
 			// Is a node and no connections, so we just pick all options
 			options = allInstances(host_model, original_typename)
-			guaranteed_instance = True
-
 		elif (read_nr_out(options) > 1):
 			// Multiple "only" options, which will not work out: no options!
 			return create_node()!
@@ -164,71 +136,22 @@ Element function get_possible_bindings(host_model : Element, schedule_model : El
 		if (bool_not(set_in(map, option))):
 			// Option is already present with another label, so skip this!
 
-			// Check if it conforms to the desired type
-			if (bool_not(guaranteed_instance)):
-				if (bool_not(is_nominal_instance(host_model, option, original_typename))):
-					// Not an actual instance, so skip!
-					continue!
-
-			// Check for local (matching) constraints of element
+			// Check for local constraints of element
 			if (element_eq(read_attribute(schedule_model, current_element, "constraint"), read_root())):
 				// No local constraints, so all is well
 				set_add(filtered_options, option)
 			else:
 				// Check local constraints and add only if positive
 				Element constraint_function
-				Boolean result
-				Element func
-
 				constraint_function = read_attribute(schedule_model, current_element, "constraint")
-				func = get_func_AL_model(import_node(constraint_function))
-				result = func(host_model, option)
-
+				Boolean result
+				result = constraint_function(host_model, option)
 				if (result):
 					set_add(filtered_options, option)
 
-	Element attributes
-	String attribute
-	Element value
-	Element func
-	Boolean result
-	Element attributes_copy
-
-	options = filtered_options
-	filtered_options = create_node()
-
-	// Check whether all attributes have a satisfied condition
-	attributes_copy = dict_keys(getAttributeList(schedule_model, current_element))
+	return filtered_options!
 
-	while (read_nr_out(options) > 0):
-		option = set_pop(options)
-		attributes = set_copy(attributes_copy)
-
-		result = True
-		while (read_nr_out(attributes) > 0):
-			attribute = set_pop(attributes)
-			if (bool_not(string_startswith(attribute, "constraint_"))):
-				continue!
-
-			value = read_attribute(schedule_model, current_element, attribute)
-			// Attribute might be undefined, so skip if it is
-			if (element_neq(value, read_root())):
-				func = get_func_AL_model(import_node(value))
-				result = func(read_attribute(host_model, option, string_substr(attribute, string_len("constraint_"), string_len(attribute) + 1)))
-			else:
-				result = True
-
-			if (bool_not(result)):
-				break!
-
-		// Check value of last result, which will be True if all passed, or False otherwise
-		if (result):
-			set_add(filtered_options, option)
-
-	options = filtered_options
-	return options!
-
-Element function full_match(host_model : Element, schedule_model : Element, current : String, single_ok : Boolean):
+Element function full_match(host_model : Element, schedule_model : Element, current : String):
 	Element NACs
 	String LHS
 	String NAC
@@ -265,9 +188,6 @@ Element function full_match(host_model : Element, schedule_model : Element, curr
 		if (allowed):
 			set_add(final_mappings, mapping)
 
-			if (single_ok):
-				break!
-
 	return final_mappings!
 
 Element function match(host_model : Element, schedule_model : Element, LHS : String, initial_mapping : Element):
@@ -288,9 +208,8 @@ Element function match(host_model : Element, schedule_model : Element, LHS : Str
 
 	mappings = create_node()
 	set_add(mappings, initial_mapping)
-	while (read_nr_out(schedule) > 0):
-		current_element = list_pop(schedule, read_nr_out(schedule) - 1)
-		//log("Binding element with label " + cast_v2s(read_attribute(schedule_model, current_element, "label")))
+	while (bool_and(read_nr_out(schedule) > 0, read_nr_out(mappings) > 0)):
+		current_element = list_pop(schedule, 0)
 		new_mappings = create_node()
 
 		while (read_nr_out(mappings) > 0):
@@ -300,30 +219,20 @@ Element function match(host_model : Element, schedule_model : Element, LHS : Str
 			while (read_nr_out(options) > 0):
 				option = set_pop(options)
 				new_map = dict_copy(map)
-				dict_add_fast(new_map, read_attribute(schedule_model, current_element, "label"), option)
+				dict_add(new_map, read_attribute(schedule_model, current_element, "label"), option)
 				set_add(new_mappings, new_map)
 
 		mappings = new_mappings
-		//log("Remaining options: " + cast_v2s(read_nr_out(mappings)))
-
-		if (read_nr_out(mappings) == 0):
-			// Stop because we have no more options remaining!
-			return create_node()!
 
 	// Finished, so try the global constraint
-	String constraint
-	Element func
-	Boolean result
+	Element constraint
 
 	new_mappings = create_node()
 	constraint = read_attribute(schedule_model, LHS, "constraint")
 	if (element_neq(constraint, read_root())):
 		while (read_nr_out(mappings) > 0):
 			map = set_pop(mappings)
-			func = get_func_AL_model(import_node(constraint))
-			result = func(host_model, map)
-
-			if (result):
+			if (constraint(host_model, map)):
 				set_add(new_mappings, map)
 		mappings = new_mappings
 
@@ -348,12 +257,10 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 	Element RHS_map
 	String tmp
 	Element value
+	Element value_function
 	Element action
 	Element original_RHS_labels
 
-	Element reverse
-	reverse = make_reverse_dictionary(schedule_model["model"])
-
 	LHS_labels = dict_keys(mapping)
 	RHS_labels = create_node()
 	RHS_map = create_node()
@@ -363,7 +270,7 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 		tmp = set_pop(RHS_elements)
 		label = read_attribute(schedule_model, tmp, "label")
 		set_add(RHS_labels, label)
-		dict_add_fast(RHS_map, label, tmp)
+		dict_add(RHS_map, label, tmp)
 
 	remaining = set_overlap(LHS_labels, RHS_labels)
 	original_RHS_labels = set_copy(RHS_labels)
@@ -379,64 +286,44 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 
 	while (read_nr_out(labels_to_add) > 0):
 		// Add the elements linked to these labels
-		label = list_pop(labels_to_add, read_nr_out(labels_to_add) - 1)
-		if (is_edge(schedule_model["model"][RHS_map[label]])):
-			// Edge
-			src = read_attribute(schedule_model, reverse[cast_id2s(read_edge_src(schedule_model["model"][RHS_map[label]]))], "label")
-			dst = read_attribute(schedule_model, reverse[cast_id2s(read_edge_dst(schedule_model["model"][RHS_map[label]]))], "label")
+		label = list_pop(labels_to_add, 0)
+		if (element_neq(read_attribute(schedule_model, RHS_map[label], "value"), read_root())):
+			// There is a value associated with this node
+			value_function = read_attribute(schedule_model, RHS_map[label], "value")
+			value = value_function(host_model, mapping)
+
+			typename = read_type(schedule_model, RHS_map[label])
+			original_typename = string_substr(typename, 5, string_len(typename))
+			new_name = instantiate_value(host_model, original_typename, "", value)
+			dict_add(new_mapping, label, new_name)
 
+		elif (is_edge(schedule_model["model"][RHS_map[label]])):
+			// Edge
+			src = read_attribute(schedule_model, reverseKeyLookup(schedule_model["model"], read_edge_src(schedule_model["model"][RHS_map[label]])), "label")
+			dst = read_attribute(schedule_model, reverseKeyLookup(schedule_model["model"], read_edge_dst(schedule_model["model"][RHS_map[label]])), "label")
 			// First check whether both source and destination are already created
 			if (bool_and(dict_in(new_mapping, src), dict_in(new_mapping, dst))):
 				// Both are present, so we can make the link
 				typename = read_type(schedule_model, RHS_map[label])
 				original_typename = string_substr(typename, 5, string_len(typename))
 				new_name = instantiate_link(host_model, original_typename, "", new_mapping[src], new_mapping[dst])
-				dict_add_fast(new_mapping, label, new_name)
+				dict_add(new_mapping, label, new_name)
 			else:
 				// Delay this a bit, until all are bound
-				list_insert(labels_to_add, label, 0)
+				list_append(labels_to_add, label)
 		else:
 			// Node
 			// Create the node and add it
 			typename = read_type(schedule_model, RHS_map[label])
 			original_typename = string_substr(typename, 5, string_len(typename))
 			new_name = instantiate_node(host_model, original_typename, "")
-			dict_add_fast(new_mapping, label, new_name)
-
-	Element attributes
-	String attribute
-	Element result
-	Element func
+			dict_add(new_mapping, label, new_name)
 
 	while (read_nr_out(original_RHS_labels) > 0):
-		// Perform actions
 		label = set_pop(original_RHS_labels)
-
-		// Do all attribute actions that are defined
-		attributes = dict_keys(getAttributeList(schedule_model, RHS_map[label]))
-		while (read_nr_out(attributes) > 0):
-			attribute = set_pop(attributes)
-			if (bool_not(string_startswith(attribute, "value_"))):
-				continue!
-
-			value = read_attribute(schedule_model, RHS_map[label], attribute)
-			if (element_neq(value, read_root())):
-				func = get_func_AL_model(import_node(value))
-				result = func(host_model, new_mapping[label], mapping)
-
-				if (has_value(result)):
-					// New value defined, so assign!
-					instantiate_attribute(host_model, new_mapping[label], string_substr(attribute, string_len("value_"), string_len(attribute) + 1), result)
-				else:
-					// Non-value return means to destroy the attribute!
-					unset_attribute(host_model, new_mapping[label], string_substr(attribute, string_len("value_"), string_len(attribute) + 1))
-
-		// Do the global action of each element
 		action = read_attribute(schedule_model, RHS_map[label], "action")
 		if (element_neq(action, read_root())):
-			Element func
-			func = get_func_AL_model(import_node(action))
-			func(host_model, new_mapping[label], mapping)
+			action(host_model, new_mapping[label], mapping)
 
 	while (read_nr_out(labels_to_remove) > 0):
 		// Remove the elements linked to these labels
@@ -447,9 +334,7 @@ Void function rewrite(host_model : Element, schedule_model : Element, RHS : Stri
 	// Execute global action (whatever it may be)
 	action = read_attribute(schedule_model, RHS, "action")
 	if (element_neq(action, read_root())):
-		Element func
-		func = get_func_AL_model(import_node(action))
-		func(host_model, new_mapping)
+		action(host_model, new_mapping)
 
 	return!
 
@@ -487,7 +372,6 @@ Boolean function transform_composite(host_model : Element, schedule_model : Elem
 
 	current = set_pop(allAssociationDestinations(schedule_model, composite, "Initial"))
 	while (is_nominal_instance(schedule_model, current, "Rule")):
-		//log("Executing " + current)
 		// Still a rule that we must execute
 		typename = read_type(schedule_model, current)
 		if (typename == "Atomic"):
@@ -514,7 +398,7 @@ Boolean function transform_atomic(host_model : Element, schedule_model : Element
 	// Execute the atomic transformation
 	Element mappings
 	Element mapping
-	mappings = full_match(host_model, schedule_model, current, True)
+	mappings = full_match(host_model, schedule_model, current)
 
 	if (read_nr_out(mappings) > 0):
 		// Pick one!
@@ -533,14 +417,13 @@ Boolean function transform_forall(host_model : Element, schedule_model : Element
 	Element mapping
 	Boolean result
 
-	mappings = full_match(host_model, schedule_model, current, False)
+	mappings = full_match(host_model, schedule_model, current)
 
 	if (read_nr_out(mappings) > 0):
 		result = True
 	else:
 		result = False
 
-	//log("Matches in forall: " + cast_v2s(read_nr_out(mappings)))
 	while (read_nr_out(mappings) > 0):
 		mapping = set_pop(mappings)
 		// TODO check if there are actually no deletions happening in the meantime of other matched elements...
@@ -553,7 +436,7 @@ Boolean function transform_query(host_model : Element, schedule_model : Element,
 	// Execute the transformation
 	Element mappings
 	Element mapping
-	mappings = full_match(host_model, schedule_model, current, True)
+	mappings = full_match(host_model, schedule_model, current)
 
 	if (read_nr_out(mappings) > 0):
 		return True!

Разница между файлами не показана из-за своего большого размера
+ 1256 - 0
core/core_algorithm.alc


+ 118 - 0
core/core_formalism.mvc

@@ -0,0 +1,118 @@
+import models/SimpleClassDiagrams as SimpleClassDiagrams
+include "primitives.alh"
+
+SimpleClassDiagrams CoreFormalism {
+    Class String {
+        $
+            if (bool_not(is_physical_string(self))):
+                return "String has no string value"!
+            else:
+                return "OK"!
+        $
+    }
+
+    Class Permissions {
+        $
+            if (bool_not(is_physical_string(self))):
+                return "Permissions has no string value"!
+            else:
+                return "OK"!
+        $
+    }
+
+    Class Boolean {
+        $
+            if (bool_not(is_physical_boolean(self))):
+                return "Boolean has no bool value"!
+            else:
+                return "OK"!
+        $
+    }
+
+    Class Natural {
+        $
+            if (bool_not(is_physical_int(self))):
+                return "Natural has no integer value"!
+            elif (integer_lt(self, 0)):
+                return "Natural has negative value"!
+            else:
+                return "OK"!
+        $
+    }
+
+    Class TypeMapping {
+        $
+            if (has_value(self)):
+                return "TypeMapping cannot have a value for root node!"!
+            Element keys
+            String key
+            keys = dict_keys(self)
+            while (read_nr_out(keys) > 0):
+                key = set_pop(keys)
+                if (bool_not(is_physical_string(key))):
+                    return ("Key on type mapping is not a string: " + cast_e2s(key))!
+                elif (bool_not(is_physical_string(self[key]))):
+                    return ("Value on type mapping is not a string for key " + cast_e2s(key))!
+            return "OK"!
+        $
+    }
+
+    Class User {
+        name : String
+        password : String
+        admin : Boolean
+    }
+
+    Class Group {
+        name : String
+    }
+
+    Association ownedBy (Group, User) {}
+    Association belongsTo (User, Group) {}
+
+    Class Model {
+        name : String
+        location : String
+        permissions : Permissions
+    }
+
+    Association instanceOf (Model, Model) {
+        type_mapping : TypeMapping
+    }
+
+    Association owner (Model, User) {
+        target_lower_cardinality = 1
+        target_upper_cardinality = 1
+    }
+
+    Association group (Model, Group) {
+        target_lower_cardinality = 1
+        target_upper_cardinality = 1
+    }
+
+    Class Transformation : Model {
+        name : String
+        location : String
+    }
+
+    Class ModelTransformation : Transformation {}
+
+    Class ActionLanguage : Transformation {}
+
+    Class ExternalTool : Transformation {}
+
+    Class ManualTransformation : Transformation {}
+
+    Association transformInput (Model, Transformation) {
+        name : String
+    }
+    Association transformOutput (Transformation, Model) {
+        name : String
+    }
+
+    Association tracability (Model, Model) {
+        type : String
+    }
+}
+
+export CoreFormalism to models/CoreFormalism

+ 288 - 0
core/mini_modify.alc

@@ -0,0 +1,288 @@
+include "primitives.alh"
+include "constructors.alh"
+include "object_operations.alh"
+include "library.alh"
+include "conformance_scd.alh"
+include "io.alh"
+include "metamodels.alh"
+include "modelling.alh"
+include "compilation_manager.alh"
+
+Element function modify(model : Element, write : Boolean):
+	String cmd
+
+	Element attr_list_pn
+	Element attr_keys_pn
+	String attr_key_pn
+	Element metamodel_element_pn
+	String typename
+
+	output("Model loaded, ready for commands!")
+	output("Use 'help' command for a list of possible commands")
+
+	while (True):
+		output("Please give your command.")
+		cmd = input()
+		if (cmd == "help"):
+			output("Allowed operations:")
+			if (write):
+				output(" == READ/WRITE ==")
+				output("  instantiate -- Create a new model element")
+				output("  delete      -- Delete an existing element")
+				output("  attr_add    -- Add an attribute to an element")
+				output("  attr_del    -- Delete an attribute of an element")
+				output("  attr_modify -- Modify an attribute of an element")
+				output("  constrain   -- Add a constraint function to the model")
+				output("  rename      -- Rename an existing element")
+				output("  modify      -- Modify the attributes of an element")
+				output("  retype      -- Change the type of an element")
+			else:
+				output(" == READ-ONLY ==")
+			output("  list        -- Prints the list of elements in the model")
+			output("  list_full   -- Prints the list of all elements in the model")
+			output("  types       -- Prints the list of elements that can be instantiated")
+			output("  read        -- Prints the current state of a model element")
+			output("  verify      -- Check whether the model conforms to the metamodel")
+			output("  exit        -- Leave the modification interface")
+		elif (cmd == "exit"):
+			return model!
+		elif (cmd == "instantiate"):
+			if (write):
+				String mm_type_name
+				output("Type to instantiate?")
+				mm_type_name = input()
+				if (dict_in(model["metamodel"]["model"], mm_type_name)):
+					String element_name
+					output("Name of new element?")
+					element_name = input()
+					if (dict_in(model["model"], element_name)):
+						output("Element already exists; aborting")
+					else:
+						if (is_edge(model["metamodel"]["model"][mm_type_name])):
+							output("Source name?")
+							String src_name
+							src_name = input()
+							if (dict_in(model["model"], src_name)):
+								output("Destination name?")
+								String dst_name
+								dst_name = input()
+								if (dict_in(model["model"], dst_name)):
+									instantiate_link(model, mm_type_name, element_name, src_name, dst_name)
+									output("Instantiation successful!")
+								else:
+									output("Unknown destination; aborting")
+							else:
+								output("Unknown source; aborting")
+						else:
+							instantiate_node(model, mm_type_name, element_name)
+							output("Instantiation successful!")
+				else:
+					log("Could not find element in " + set_to_string(dict_keys(model["metamodel"]["model"])))
+					output("Unknown type specified; aborting")
+			else:
+				output("Permission denied")
+
+		elif (cmd == "constrain"):
+			if (write):
+				output("Element to constrain (empty for global)?")
+				String model_name
+				model_name = input()
+
+				if (model_name == ""):
+					// Global constraint
+					output("Give input to function constructors for GLOBAL constraint!")
+					set_model_constraints(model, construct_function())
+				elif (dict_in(model["model"], model_name)):
+					// Local constraint for this model
+					output("Give input to function constructors for LOCAL constraint!")
+					add_constraint(model, model_name, construct_function())
+					output("Added constraint to model!")
+				else:
+					// Local constraint, but model not found
+					output("Unknown model; aborting")
+			else:
+				output("Permission denied")
+
+		elif (cmd == "attr_modify"):
+			if (write):
+				String model_name
+				output("Element to modify?")
+				model_name = input()
+				if (dict_in(model["model"], model_name)):
+					Element attrs
+					attrs = getAttributeList(model, model_name)
+					String attr_name
+					output("Attribute to modify?")
+					attr_name = input()
+					if (set_in(dict_keys(attrs), attr_name)):
+						output("New value?")
+						unset_attribute(model, model_name, attr_name)
+						instantiate_attribute(model, model_name, attr_name, input())
+						output("Modified!")
+					else:
+						output("No such attribute!")
+				else:
+					output("No such model!")
+			else:
+				output("Permission denied")
+
+		elif (cmd == "attr_add"):
+			if (write):
+				String model_name
+				output("Which model do you want to assign an attribute to?")
+				model_name = input()
+				if (dict_in(model["model"], model_name)):
+					Element attrs
+					attrs = getAttributeList(model, model_name)
+					String attr_name
+					output("Which attribute do you wish to assign?")
+					attr_name = input()
+					if (set_in(dict_keys(attrs), attr_name)):
+						output("Value of attribute?")
+						instantiate_attribute(model, model_name, attr_name, input())
+						output("Added attribute!")
+					else:
+						output("No such attribute!")
+				else:
+					output("No such model!")
+			else:
+				output("Permission denied")
+
+		elif (cmd == "attr_del"):
+			if (write):
+				String model_name
+				output("Which model do you want to remove an attribute of?")
+				model_name = input()
+				if (dict_in(model["model"], model_name)):
+					Element attrs
+					attrs = getAttributeList(model, model_name)
+					String attr_name
+					output("Which attribute do you want to delete?")
+					attr_name = input()
+					if (set_in(dict_keys(attrs), attr_name)):
+						unset_attribute(model, model_name, attr_name)
+						output("Attribute deleted!")
+					else:
+						output("No such attribute!")
+				else:
+					output("No such model!")
+			else:
+				output("Permission denied")
+
+		elif (cmd == "delete"):
+			if (write):
+				output("What is the name of the element you want to delete?")
+				cmd = input()
+				if (dict_in(model["model"], cmd)):
+					model_delete_element(model, cmd)
+					output("Deleted!")
+				else:
+					output("No such element; aborting")
+			else:
+				output("Permission denied")
+
+		elif (cmd == "rename"):
+			if (write):
+				output("Old name?")
+				String old_name_e
+				old_name_e = input()
+				if (dict_in(model["model"], old_name_e)):
+					output("New name?")
+					String new_name_e
+					new_name_e = input()
+					if (dict_in(model["model"], new_name_e)):
+						output("New name already used; aborting")
+					else:
+						dict_add(model["model"], new_name_e, model["model"][old_name_e])
+						dict_delete(model["model"], old_name_e)
+						output("Rename complete!")
+				else:
+					output("Unknown element; aborting")
+			else:
+				output("Permission denied")
+
+		elif (cmd == "list"):
+			Element keys_m
+			keys_m = dict_keys(model["model"])
+			output("List of all elements:")
+			String v_m
+			while (read_nr_out(keys_m) > 0):
+				v_m = set_pop(keys_m)
+				// Filter out anonymous objects
+				if (bool_not(string_startswith(v_m, "__"))):
+					typename = read_type(model, v_m)
+					output((("  " + v_m) + " : ") + typename)
+
+		elif (cmd == "list_full"):
+			Element keys_m
+			keys_m = dict_keys(model["model"])
+			output("List of all elements:")
+			String v_m
+			while (read_nr_out(keys_m) > 0):
+				v_m = set_pop(keys_m)
+				// Filter out anonymous objects
+				typename = read_type(model, v_m)
+				output((("  " + v_m) + " : ") + typename)
+
+		elif (cmd == "read"):
+			output("Element to read?")
+			cmd = input()
+			if (dict_in(model["model"], cmd)):
+				output("ID: " + cmd)
+				output("Type: " + read_type(model, cmd))
+				if (is_edge(model["model"][cmd])):
+					output("Source: " + reverseKeyLookup(model["model"], read_edge_src(model["model"][cmd])))
+					output("Destination: " + reverseKeyLookup(model["model"], read_edge_dst(model["model"][cmd])))
+				if (has_value(model["model"][cmd])):
+					output("Value: " + cast_v2s(model["model"][cmd]))
+				output("Defines attributes:")
+				attr_list_pn = getInstantiatableAttributes(model, cmd)
+				attr_keys_pn = dict_keys(attr_list_pn)
+				while (0 < read_nr_out(attr_keys_pn)):
+					attr_key_pn = set_pop(attr_keys_pn)
+					output(((("  " + attr_key_pn) + " : ") + cast_v2s(attr_list_pn[attr_key_pn])))
+				output("Attributes:")
+				attr_list_pn = getAttributeList(model, cmd)
+				attr_keys_pn = dict_keys(attr_list_pn)
+				while (0 < read_nr_out(attr_keys_pn)):
+					attr_key_pn = set_pop(attr_keys_pn)
+					output((((("  " + cast_v2s(attr_key_pn)) + " : ") + cast_v2s(attr_list_pn[attr_key_pn])) + " = ") + cast_v2s(read_attribute(model, cmd, attr_key_pn)))
+			else:
+				output("Unknown element; aborting")
+
+		elif (cmd == "verify"):
+			output(conformance_scd(model))
+
+		elif (cmd == "types"):
+			Element keys_t
+			keys_t = dict_keys(model["metamodel"]["model"])
+			output("List of types:")
+			String v_t
+			while (read_nr_out(keys_t) > 0):
+				v_t = set_pop(keys_t)
+				if (bool_not(string_startswith(v_t, "__"))):
+					output(string_join(("  " + v_t) + " : ", read_type(model, v_t)))
+
+		elif (cmd == "retype"):
+			if (write):
+				output("Element to retype?")
+				String elementname
+				elementname = input()
+				if (dict_in(model["model"], elementname)):
+					output("New type")
+					typename = input()
+					if (dict_in(model["metamodel"]["model"], typename)):
+						retype(model, elementname, typename)
+						output("Retyped!")
+					else:
+						output("Unknown type; aborting")
+				else:
+					output("Unknown element; aborting")
+			else:
+				output("Permission denied")
+
+		else:
+			output("Unknown command: " + cast_v2s(cmd))
+			output("Use command 'help' to get a list of available commands")
+
+	return model!

+ 1 - 0
core/mini_modify.alh

@@ -0,0 +1 @@
+Element function modify(model : Element, write : Boolean)

BIN
doc/_build/doctrees/actionlanguage.doctree


BIN
doc/_build/doctrees/advanced.doctree


BIN
doc/_build/doctrees/communication_models.doctree


BIN
doc/_build/doctrees/components.doctree


BIN
doc/_build/doctrees/examples.doctree


BIN
doc/_build/doctrees/howto.doctree


BIN
doc/_build/doctrees/index.doctree


BIN
doc/_build/doctrees/installation.doctree


BIN
doc/_build/doctrees/interface.doctree


BIN
doc/_build/doctrees/internal.doctree


BIN
doc/_build/doctrees/modellanguage.doctree


BIN
doc/_build/doctrees/models.doctree


BIN
doc/_build/doctrees/problems.doctree


+ 4 - 0
doc/_build/html/.buildinfo

@@ -0,0 +1,4 @@
+# Sphinx build info version 1
+# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
+config: e73af8526ca0a08f40b3dea3312b2ada
+tags: 645f666f9bcd5a90fca523b33c5a78b7

Разница между файлами не показана из-за своего большого размера
+ 5017 - 0
doc/_build/html/_images/mvk_server.svg


Разница между файлами не показана из-за своего большого размера
+ 1719 - 0
doc/_build/html/_images/mvs_server.svg


+ 425 - 0
doc/_build/html/_images/overview.svg

@@ -0,0 +1,425 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   width="276.66025"
+   height="117.87283"
+   xml:space="preserve"
+   sodipodi:docname="Modelverse.pdf"><metadata
+     id="metadata8"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+     id="defs6" /><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1790"
+     inkscape:window-height="1422"
+     id="namedview4"
+     showgrid="false"
+     inkscape:zoom="3.6293311"
+     inkscape:cx="134.83208"
+     inkscape:cy="52.314662"
+     inkscape:window-x="0"
+     inkscape:window-y="16"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g10" /><g
+     id="g10"
+     inkscape:groupmode="layer"
+     inkscape:label="Modelverse"
+     transform="matrix(1.25,0,0,-1.25,0,117.87283)"><text
+       id="text14"
+       transform="scale(1,-1)"
+       x="182.43848"
+       y="-87.612328"><tspan
+         id="tspan16"
+         sodipodi:role="line"
+         style="font-size:8.80000019px;font-variant:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans-Bold"
+         x="182.43848"
+         y="-87.612328">MvS</tspan></text>
+<text
+       id="text18"
+       transform="scale(1.1052783,-0.90474952)"
+       x="59.262783"
+       y="-96.698273"
+       style="font-size:10.85699463px"><tspan
+         id="tspan20"
+         sodipodi:role="line"
+         y="-96.698273"
+         x="59.262783 68.018784 73.747581"
+         style="font-size:8.80000019px;font-variant:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans-Bold">MvK</tspan></text>
+<text
+       id="text22"
+       transform="scale(1,-1)"
+       x="11.363914"
+       y="-87.612328"><tspan
+         id="tspan24"
+         sodipodi:role="line"
+         style="font-size:8.80000019px;font-variant:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans-Bold"
+         x="11.363914"
+         y="-87.612328">MvI</tspan></text>
+<g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g26"><path
+         inkscape:connector-curvature="0"
+         id="path28"
+         style="fill:none;stroke:#000000;stroke-width:0.75819701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 52.336,94.051 0,-80.719" /></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g30"><path
+         inkscape:connector-curvature="0"
+         id="path32"
+         style="fill:none;stroke:#000000;stroke-width:0.75819701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 50.621,94.051 0,-80.719" /></g><text
+       id="text58"
+       transform="scale(1.1052783,-0.90474952)"
+       x="51.781845"
+       y="-15.086186"
+       style="font-size:10.85699463px"><tspan
+         id="tspan60"
+         sodipodi:role="line"
+         y="-15.086186"
+         x="51.781845 56.677845 61.229843 66.149841 69.285843 72.573845 74.789848 80.773842 85.693848"
+         style="font-size:8px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans">aPetriNet</tspan></text>
+<g
+       id="g3322"><text
+         style="font-size:10.85699463px"
+         y="-66.704163"
+         x="58.160751"
+         transform="scale(1.1052783,-0.90474952)"
+         id="text34"><tspan
+           style="font-size:8px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans"
+           x="58.160751 65.056747 71.952751 77.536751"
+           y="-66.704163"
+           sodipodi:role="line"
+           id="tspan36">MMCL</tspan></text>
+<g
+         id="g38"
+         transform="matrix(1,0,0,-1,0,94.298264)"><path
+           d="m 69.203,24.816 0,-11.718 15.957,0 0,10.91"
+           style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:0.8, 0.8;stroke-dashoffset:0"
+           id="path40"
+           inkscape:connector-curvature="0" /></g><g
+         id="g42"
+         transform="matrix(0,-1,-1,0,0,94.298264)"><path
+           d="m 25.852,-85.16 -2.766,1.598 0,-3.2 2.766,1.602 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path44"
+           inkscape:connector-curvature="0" /></g><text
+         style="font-size:10.85699463px"
+         y="-40.892929"
+         x="54.082626"
+         transform="scale(1.1052783,-0.90474952)"
+         id="text46"><tspan
+           style="font-size:8px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans"
+           x="54.082626 58.626625 63.546627 66.682625 69.970627 72.186623 78.170624 83.09063"
+           y="-40.892929"
+           sodipodi:role="line"
+           id="tspan48">PetriNet</tspan></text>
+<g
+         id="g50"
+         transform="matrix(1,0,0,-1,0,94.298264)"><path
+           d="m 77.883,49.363 0,-11.945"
+           style="fill:none;stroke:#000000;stroke-width:0.64837497;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:0.648375, 0.648375;stroke-dashoffset:0"
+           id="path52"
+           inkscape:connector-curvature="0" /></g><g
+         id="g54"
+         transform="matrix(0,1,1,0,0,94.298264)"><path
+           d="m -35.922,77.883 -2.246,1.297 0,-2.594 2.246,1.297 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.32418799;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path56"
+           inkscape:connector-curvature="0" /></g><g
+         id="g62"
+         transform="matrix(1,0,0,-1,0,94.298264)"><path
+           d="m 77.883,72.711 0,-11.941"
+           style="fill:none;stroke:#000000;stroke-width:0.64837497;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:0.648375, 0.648375;stroke-dashoffset:0"
+           id="path64"
+           inkscape:connector-curvature="0" /></g><g
+         id="g66"
+         transform="matrix(0,1,1,0,0,94.298264)"><path
+           d="m -59.273,77.883 -2.243,1.297 0,-2.594 2.243,1.297 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.32418799;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path68"
+           inkscape:connector-curvature="0" /></g><text
+         y="-1.3312531"
+         x="66.653641"
+         transform="scale(1,-1)"
+         id="text70"><tspan
+           style="font-size:6.4000001px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans"
+           x="66.653641 70.103241 74.013641 78.071236 79.84404 83.357643 87.274437"
+           y="-1.3312531"
+           sodipodi:role="line"
+           id="tspan72">Logical</tspan></text>
+</g><g
+       id="g3301"><g
+         id="g92"
+         transform="matrix(1,0,0,-1,0,94.298264)"><path
+           d="m 10.684,53.07 c 0,2.84 -2.305,5.141 -5.145,5.141 -2.84,0 -5.144,-2.301 -5.144,-5.141 0,-2.84 2.304,-5.144 5.144,-5.144 2.84,0 5.145,2.304 5.145,5.144 z"
+           style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path94"
+           inkscape:connector-curvature="0" /></g><g
+         id="g96"
+         transform="matrix(1,0,0,-1,0,94.298264)"><path
+           d="m 39.824,64.641 c 0,2.839 -2.301,5.144 -5.14,5.144 -2.84,0 -5.145,-2.305 -5.145,-5.144 0,-2.84 2.305,-5.145 5.145,-5.145 2.839,0 5.14,2.305 5.14,5.145 z"
+           style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path98"
+           inkscape:connector-curvature="0" /></g><g
+         id="g100"
+         transform="matrix(1,0,0,-1,0,94.298264)"><path
+           d="m 40.109,42.355 c 0,2.84 -2.3,5.141 -5.14,5.141 -2.84,0 -5.145,-2.301 -5.145,-5.141 0,-2.839 2.305,-5.144 5.145,-5.144 2.84,0 5.14,2.305 5.14,5.144 z"
+           style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path102"
+           inkscape:connector-curvature="0" /></g><path
+         d="m 19.109,48.372 3.285,0 0,-13.145 -3.285,0 0,13.145 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path104"
+         inkscape:connector-curvature="0" /><g
+         id="g106"
+         transform="matrix(1,0,0,-1,0,94.298264)"><path
+           d="m 10.617,53.02 6.27,0"
+           style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path108"
+           inkscape:connector-curvature="0" /></g><g
+         id="g110"
+         transform="matrix(1,0,0,-1,0,94.298264)"><path
+           d="m 18.73,53.02 -2.765,1.597 0,-3.199 2.765,1.602 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path112"
+           inkscape:connector-curvature="0" /></g><g
+         id="g114"
+         transform="matrix(1,0,0,-1,0,94.298264)"><path
+           d="m 21.328,52.742 7.57,-5.57"
+           style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path116"
+           inkscape:connector-curvature="0" /></g><g
+         id="g118"
+         transform="matrix(1,0.73585,0.73585,-1,0,94.298264)"><path
+           d="m -2.283,44.398 -2.23,1.289 -0.001,-2.579 2.231,1.29 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.322175;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path120"
+           inkscape:connector-curvature="0" /></g><g
+         id="g122"
+         transform="matrix(1,0,0,-1,0,94.298264)"><path
+           d="m 21.402,52.512 7.286,7.285"
+           style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path124"
+           inkscape:connector-curvature="0" /></g><g
+         id="g126"
+         transform="matrix(1,-1,-1,-1,0,94.298264)"><path
+           d="m 45.549,15.553 -1.957,1.133 0,-2.262 1.957,1.129 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.28284299;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path128"
+           inkscape:connector-curvature="0" /></g></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g130"><path
+         inkscape:connector-curvature="0"
+         id="path132"
+         style="fill:none;stroke:#000000;stroke-width:0.75819701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 106.332,94.051 0,-80.719" /></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g134"><path
+         inkscape:connector-curvature="0"
+         id="path136"
+         style="fill:none;stroke:#000000;stroke-width:0.75819701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 104.617,94.051 0,-80.719" /></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g138"><path
+         inkscape:connector-curvature="0"
+         id="path140"
+         style="fill:none;stroke:#000000;stroke-width:0.75819701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 155.188,94.051 0,-80.719" /></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g142"><path
+         inkscape:connector-curvature="0"
+         id="path144"
+         style="fill:none;stroke:#000000;stroke-width:0.75819701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 153.473,94.051 0,-80.719" /></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g146"><path
+         inkscape:connector-curvature="0"
+         id="path148"
+         style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.4, 0.8;stroke-dashoffset:0"
+         d="m 139.473,54.047 35.715,19" /></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g154"><path
+         inkscape:connector-curvature="0"
+         id="path156"
+         style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.4, 0.8;stroke-dashoffset:0"
+         d="m 139.473,53.832 30.859,2.215" /></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g162"><path
+         inkscape:connector-curvature="0"
+         id="path164"
+         style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.4, 0.8;stroke-dashoffset:0"
+         d="M 139.473,53.762 177.332,39.117" /></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g170"><path
+         inkscape:connector-curvature="0"
+         id="path172"
+         style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.4, 0.8;stroke-dashoffset:0"
+         d="M 139.332,53.832 172.617,21.547" /></g><g
+       id="g3348"><text
+         y="-76.728882"
+         x="171.77673"
+         transform="scale(1,-1)"
+         id="text74"><tspan
+           style="font-size:8px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans"
+           x="171.77673 174.12872 179.19273 182.07272 188.96873 193.88873 201.68073 206.56873 209.88074"
+           y="-76.728882"
+           sodipodi:role="line"
+           id="tspan76">In-Memory</tspan><tspan
+           style="font-size:8px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans"
+           x="171.77673 176.84872 183.14473 188.21674 190.43272 195.35274 199.74474 202.88074"
+           y="-66.728882"
+           sodipodi:role="line"
+           id="tspan78"> Objects</tspan><tspan
+           style="font-size:8px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans"
+           x="173.224 178.424 183.34399 185.56 190.45599 193.592 195.808 200.696 205.75999 210.65599"
+           y="-38.306622"
+           sodipodi:role="line"
+           id="tspan80">Relational</tspan><tspan
+           style="font-size:8px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans"
+           x="173.224 179.38399 184.28 187.416 192.312 197.38399 202.28 206.44"
+           y="-28.306622"
+           sodipodi:role="line"
+           id="tspan82">Database</tspan><tspan
+           style="font-size:8px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans"
+           x="181.80408 187.38808 189.60408 194.49208 199.55608"
+           y="-52.068558"
+           sodipodi:role="line"
+           id="tspan84">Cloud</tspan><tspan
+           style="font-size:8px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans"
+           x="184.77478 190.32678 196.48679"
+           y="-14.611133"
+           sodipodi:role="line"
+           id="tspan86">RDF</tspan></text>
+<text
+         y="-1.3312531"
+         x="168.73727"
+         transform="scale(1,-1)"
+         id="text88"><tspan
+           style="font-size:6.4000001px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans"
+           x="168.73727 172.89728 176.83328 180.89088 183.38689 187.32288 190.65088 194.58688 198.63808 201.14688 205.06367 207.59167 209.36449 213.27489"
+           y="-1.3312531"
+           sodipodi:role="line"
+           id="tspan90">Representation</tspan></text>
+<g
+         id="g150"
+         transform="matrix(1,-0.532,-0.532,-1,0,94.298264)"><path
+           d="m 168.463,-15.709 -2.443,1.414 -0.004,-2.827 2.447,1.413 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.353136;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path152"
+           inkscape:connector-curvature="0" /></g><g
+         id="g158"
+         transform="matrix(1,-0.0717593,-0.0717593,-1,0,94.298264)"><path
+           d="m 175.301,43.6 -2.761,1.593 0.001,-3.192 2.76,1.599 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.398974;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path160"
+           inkscape:connector-curvature="0" /></g><g
+         id="g166"
+         transform="matrix(1,0.386792,0.386792,-1,0,94.298264)"><path
+           d="m 142.815,93.693 -2.584,1.489 0.002,-2.984 2.582,1.495 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.37306499;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path168"
+           inkscape:connector-curvature="0" /></g><g
+         id="g174"
+         transform="matrix(1,0.969957,0.969957,-1,0,94.298264)"><path
+           d="m 79.497,97.37 -1.986,1.149 -10e-4,-2.298 1.987,1.149 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.28712299;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="path176"
+           inkscape:connector-curvature="0" /></g></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g178"><path
+         inkscape:connector-curvature="0"
+         id="path180"
+         style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.4, 0.8;stroke-dashoffset:0"
+         d="m 94.332,32.047 22.184,18.301" /></g><g
+       transform="matrix(1,-0.825014,-0.825014,-1,0,94.298264)"
+       id="g182"><path
+         inkscape:connector-curvature="0"
+         id="path184"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.30854699;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 95.466,-27.237 -2.134,1.233 -10e-4,-2.468 2.135,1.235 z" /></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g186"><path
+         inkscape:connector-curvature="0"
+         id="path188"
+         style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.4, 0.8;stroke-dashoffset:0"
+         d="m 97.902,54.402 17.93,0" /></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g190"><path
+         inkscape:connector-curvature="0"
+         id="path192"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 117.676,54.402 -2.766,1.602 0,-3.199 2.766,1.597 z" /></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g194"><path
+         inkscape:connector-curvature="0"
+         id="path196"
+         style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.4, 0.8;stroke-dashoffset:0"
+         d="M 100.152,73.836 116.605,58.5" /></g><g
+       transform="matrix(1,0.932142,0.932142,-1,0,94.298264)"
+       id="g198"><path
+         inkscape:connector-curvature="0"
+         id="path200"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.29259601;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 34.566,89.462 -2.026,1.171 -10e-4,-2.341 2.027,1.17 z" /></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g202"><path
+         inkscape:connector-curvature="0"
+         id="path204"
+         style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:2.4, 0.8;stroke-dashoffset:0"
+         d="m 42.719,54.66 13.129,0" /></g><g
+       transform="matrix(1,0,0,-1,0,94.298264)"
+       id="g206"><path
+         inkscape:connector-curvature="0"
+         id="path208"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.40000001;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 57.695,54.66 -2.769,1.602 0,-3.203 2.769,1.601 z" /></g><g
+       id="g3342"><text
+         y="-36.237572"
+         x="121.38362"
+         transform="scale(1,-1)"
+         id="text210"><tspan
+           style="font-size:8px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans"
+           x="121.38362 126.20762 131.08762"
+           y="-36.237572"
+           sodipodi:role="line"
+           id="tspan212">PTM</tspan></text>
+<text
+         y="-1.3312531"
+         x="117.08406"
+         transform="scale(1,-1)"
+         id="text214"><tspan
+           style="font-size:6.4000001px;font-variant:normal;font-weight:normal;writing-mode:lr-tb;fill:#008000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans"
+           x="117.08406 120.94326 124.99446 128.77686 132.10486 133.87766 137.39127 141.32726"
+           y="-1.3312531"
+           sodipodi:role="line"
+           id="tspan216">Physical</tspan></text>
+</g><text
+       id="text218"
+       transform="scale(1.1052783,-0.90474952)"
+       x="102.4316"
+       y="-96.822884"
+       style="font-size:10.85699463px"><tspan
+         id="tspan220"
+         sodipodi:role="line"
+         y="-96.822884"
+         x="102.4316 108.882 114.9276 124.0884"
+         style="font-size:8.80000019px;font-variant:normal;font-weight:bold;writing-mode:lr-tb;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:DejaVuSans-Bold">Comm</tspan></text>
+</g></svg>

BIN
doc/_build/html/_images/prompt_fibonacci.png


BIN
doc/_build/html/_images/prompt_fibonacci_more.png


BIN
doc/_build/html/_images/prompt_pn_interface.png


+ 296 - 0
doc/_build/html/_sources/actionlanguage.txt

@@ -0,0 +1,296 @@
+Action Language
+===============
+
+The primary language of the Modelverse, is its action language.
+This language serves as a nicer representation of the underlying Modelverse Graph Language, which is stored as a graph.
+The action language gets parsed by the parser, resulting in a kind of abstract syntax graph.
+This abstract syntax graph highly resembles an executable graph in the Modelverse Graph Language.
+
+Users will mainly use this language to write actions and constraints, but maybe also to implement their own interfaces, or override core functionality of the Modelverse.
+
+.. warning::
+   The current parser is unable to handle whitespaces in a general way.
+   As such, all indentation needs to be done using tabs, and the difference needs to be exactly 1.
+   This is different from Python, where tabs and whitespaces can be mixed, and the number can even vary.
+
+Files
+-----
+
+There are two kinds of files: code files, and headers.
+This distinction is similar to C and related languages.
+Code in header files will always be copied throughout all including files.
+As such, it is a good idea to have header files which declare the signatures of functions, but leave the actual implementation to the code files.
+Code files do not need to import the headers they are implementing: all variable names are automatically shared.
+
+Language description
+--------------------
+
+The language is inspired by Python syntax, and highly resembles it.
+Nonetheless, it is a lot simpler.
+In the remainder of this subsection, we go over the different language constructs.
+
+If
+^^
+
+The IF construct is similar to that found in other languages.
+Its structure is as follows::
+
+    if condition1:
+       do_when_condition1
+    elif condition2:
+       do_when_condition2
+    else:
+       do_otherwise
+
+Each condition can be an expression.
+The code blocks can be any other kind of code.
+Just like Python, indentation is the only way to structure code.
+Unlike Python, only tabs are allowed (thus no space), and the number of tabs must be exactly one higher for a deeper block.
+
+The presence of an "elif" and "else" is optional.
+
+While
+^^^^^
+
+The WHILE construct is similar to that found in other languages.
+Contrary to Python, there is no support for the "else" construct.
+Its structure is as follows::
+
+    while condition:
+        action
+
+Conditions and actions are similar to the If construct.
+
+Break
+^^^^^
+
+Whereas this is supported in the Modelverse, the parser currently does not consider this keyword.
+
+Continue
+^^^^^^^^
+
+Whereas this is supported in the Modelverse, the parser currently does not consider this keyword.
+
+Return
+^^^^^^
+
+The RETURN construct is again similar to how it is expected.
+To prevent ambiguity in the grammar, an exclamation mark should follow after the expression to return.
+Its structure is as follows::
+
+    return expression!
+
+The expression can be any expression, similar to the condition in an If and While.
+
+Function call
+^^^^^^^^^^^^^
+
+Function calls happen like usual, by appending an opening and closing parenthesis at the end.
+Its structure is as follows::
+
+    my_function(argument_a, argument_b)
+
+Arguments can again be any kind of expression.
+Named parameters are not supported in the grammar, though the Modelverse can internally handle them.
+
+Function definition
+^^^^^^^^^^^^^^^^^^^
+
+Defining a function makes the function available as a variable in the remainder of the context.
+Forward declaration is unnecessary: all function names are retrieved before going over the body of the functions.
+This makes mutual recursion easy.
+
+A function needs to define its return type, as well as the type of all its parameters.
+In case the type is unknown, or can be anything, *Element* can be used as a kind of "void pointer".
+Its structure is as follows::
+
+    Element function function_name(parameter_a : Integer):
+        body_of_the_function
+
+First comes the returntype, followed by the keyword "function".
+Again, indentation needs to happen using tabs.
+
+Assignment
+^^^^^^^^^^
+
+Assignment is like usual.
+Its structure is::
+
+    a = expression
+
+This assumes that a is already defined.
+
+Declaration
+^^^^^^^^^^^
+
+All variables used in the Modelverse need to be defined statically.
+Defining a variable reserves a part of the Modelverse State to hold the value for this value.
+As such, variables cannot be used if they are not defined.
+Additionally, a declared variable will have a type defined with it.
+Again, if the type can vary or is unknown, this can be *Element*.
+
+.. warning::
+   Contrary to other languages, declaring a variable does not equal defining the variable.
+   Therefore, after a variable is declared, it can be used, but its contents will be non-existing.
+   It is wise to always assign a value to a declared value right after declaration!
+
+Its structure is as follows::
+
+    String abc
+
+There are two kinds of declaration: local declaration, and global declaration.
+Local declarations happen in the current block of the code, and their references get removed when exiting the block.
+Global declarations have identically the same syntax, but are specified at the top level (*i.e.*, they have no tabs in front of them).
+Global declarations do not assign a value and are thus external references, to be defined in the future or by some other module.
+Sharing between modules is possible this way, as all global names are linked together when linking the application together.
+A global declaration that is never defined is flagged as invalid by the compiler and will prevent compilation.
+
+Definition
+^^^^^^^^^^
+
+Defining a variable is similar to a global declaration, but now there is an immediate assignment.
+Immediate assignment is only possible at the top level.
+Note that the assignment must be of a constant which requires no execution of functions or such.
+Also, it is impossible to assign the value of another variable.
+
+Its structure is as follows::
+
+    String abc = "abc"
+
+It is possible that a definition does not yet know the value to assign, or is an empty element.
+To notify the other files that this is the defining element, use the import syntax to assign *?* to it::
+
+    Element abc = ?
+
+This results in the Modelverse creating an empty node as placeholder for a value.
+The value will now be defined and accessible.
+
+Imports
+^^^^^^^
+
+Direct imports in the Modelverse are possible, but are not recommended for ordinary users.
+This syntax allows a variable to be bound to an absolute location in the Modelverse, which is resolved at compile time.
+The primary use case for this is the creation of bootstrap files, but it is also possible for other purposes.
+Use with care!
+
+Its structure is as follows::
+
+    String abc = ?path/in/modelverse
+
+A special case is when the path is empty, which indicates that a new (anonymous) node should be created for it::
+
+    Element abc = ?
+
+Include
+^^^^^^^
+
+Other files can easily be included using the include syntax.
+This is a raw include: the contents of the file are just copied inside the file at that exact spot.
+Generally, you should only include *.alh* files, unless you know what you are doing.
+
+Constants
+^^^^^^^^^
+
+The Modelverse supports a set of constants that can be used.
+All constants can be assigned in a definition of globals.
+
+============= ========================================================================== =======
+Constant type Values                                                                     Example
+============= ========================================================================== =======
+Integer       Any possible integer, either positive (no prefix) or negative (- prefix)   1
+Float         Any possible floating point value; scientific notation is not supported    1.0
+Boolean       Either True or False                                                       True
+String        Any possible string, enclosed with either double or single quotes          "abc"
+Action        An action construct from the Modelverse, prefixed with an exclamation mark !If
+============= ========================================================================== =======
+
+Operators
+^^^^^^^^^
+
+While operators are seemingly supported by the compiler, these are actually expanded to function calls to relevant functions.
+For example, *1 + 2*, is expanded to *integer_addition(1, 2)*
+
+User I/O
+^^^^^^^^
+
+User input and output is done through the keyworded operations *input()* and *output(msg)*.
+*input()* returns the first message in the input queue of the current user.
+*output(msg)* places the value of the expression in the output queue of the current user.
+
+All I/O is done using queues: the value is only read and written to a specific place in the Modelverse.
+To actually read or write it at the client side, these special places should be accessed through dedicated Modelverse operations.
+
+Examples
+--------
+
+We now show some simple code fragments written in valid Action Language code.
+As this code is directly executable in the Modelverse, the main function is always called "main" and all includes are also present.
+We do not currently handle how to execute this code: this is explained further on.
+
+Fibonacci
+^^^^^^^^^
+
+The Fibonacci code is fairly simple.
+First, the primitives are imported to make sure that we know about all operations on primitives.
+Then, a function *fib* is defined, which will recursively compute the specified Fibonacci number.
+This is wrapped by a *main* function, which takes input from the user and outputs the result of the *fib* function.
+
+This code looks as follows::
+
+    include "primitives.alh"
+
+    Integer function fib(param : Integer):
+        if (param <= 2):
+            return 1!
+        else:
+            return fib(param - 1) + fib(param - 2)!
+
+    Void function main():
+        while(True):
+            output(fib(input()))
+
+Factorial
+^^^^^^^^^
+
+Similarly, the code for computing a factorial is given below::
+
+    include "primitives.alh"
+
+    Integer function factorial(n : Integer):
+        if(n <= 1):
+            return 1!
+        else:
+            return n * factorial(n - 1)!
+
+    Void function main():
+        while(True):
+            output(factorial(input()))
+
+Binary to decimal converter
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A simple binary to decimal converter is given below::
+
+    include "primitives.alh"
+
+    Integer function b2d(param : String):
+        Integer value
+        value = 0
+        Integer length
+        length = string_len(param)
+        Integer counter
+        counter = integer_subtraction(length, 1)
+        Integer accumul
+        accumul = 1
+
+        while (counter >= 0):
+            if (string_get(param, counter) == "1"):
+                value = integer_addition(value, accumul)
+            accumul = integer_multiplication(accumul, 2)
+            counter = integer_subtraction(counter, 1)
+
+        return value!
+
+    Void function main():
+        while(True):
+            output(b2d(input()))

+ 14 - 0
doc/_build/html/_sources/advanced.txt

@@ -0,0 +1,14 @@
+Advanced examples
+=================
+
+These advanced examples show you how the core algorithms of the Modelverse are implemented and how you can potentially modify them.
+This part is still TODO, since this is probably not of interest to you.
+
+Inheritance Semantics
+---------------------
+
+Instantiation Semantics
+-----------------------
+
+Conformance Semantics
+---------------------

+ 42 - 0
doc/_build/html/_sources/communication_models.txt

@@ -0,0 +1,42 @@
+Communication models
+====================
+
+The network communication in the Modelverse builds on top of the raw socket implementation of Python.
+Whereas we use normal HTTP requests, we explicitly opted not to use these libraries.
+Many of these libraries hide important implementation details, such as how successive requests are handled (sequential, threaded, ...), whether or not to keep connections open and reuse them, which HTTP version to implement, and so on.
+As the HTTP protocol is a simple protocol, we reimplemented it completely in SCCD (StateCharts and Class Diagrams).
+
+There are two network components: a server in the MvS, and a server and client in the MvK.
+
+MvS server
+----------
+
+.. image:: img/mvs_server.svg
+
+The MvS server mainly just waits for incoming HTTP requests and presents the message to the MvS interface itself.
+Each part of the processing happens in a seperate orthogonal component, but in all cases, processing happens sequentially, and buffers are implemented in between each layer.
+This way, we can be certain that invocations on the MvS will always happen sequentially.
+
+The statechart consists of two parts.
+
+The topmost part is the HTTP server itself, which waits from messages from the sockets.
+When it starts up, a socket is created that listens to incoming connections.
+Messages from the socket are then processed.
+Apart from setting up the sockets, this component serializes all requests that get sent to the MvS: events are placed in a queue, and are only executed on the MvS when it has finished processing the previous request.
+
+The bottommost part is the socket server, which wraps around the socket and keeps fetching from the socket until it gets a complete HTTP request.
+The HTTP request is then split from the other data on the socket, and forwarded as a single request to the HTTP server.
+We explicitly need to check and split HTTP requests, as our protocol allows users to bundle multiple HTTP requests simultaneously.
+These requests will just come one after the other, so the socket buffer might contain two messages at the same time, or even fragments of a second request.
+A message is forwarded as soon as it is completely reconstructed.
+
+MvK server
+----------
+
+.. image:: img/mvk_server.svg
+
+.. note::
+    This figure shows the intended model, not the optimized model.
+    For performance reasons, many of these parts are merged together in the *run_local_modelverse.py* script.
+    As a result, it only implements the *MvKController*, *Server*, and *Socket* classes.
+    A more elaborate statechart implementation also exists, which does implements this whole figure.

+ 47 - 0
doc/_build/html/_sources/components.txt

@@ -0,0 +1,47 @@
+Modelverse components
+=====================
+
+The Modelverse consists of three individual projects, which are linked together to construct the Modelverse.
+Each of these projects stands alone and has its own concerns.
+A socket interface to communicate with the other components is provided.
+By using sockets, it becomes possible to switch everything about the implementation, even the implementation language, without endangering interoperability.
+
+The three projects are:
+1. Modelverse State
+2. Modelverse Kernel
+3. Modelverse Interface
+
+.. image:: img/overview.svg
+
+Modelverse State (MvS)
+----------------------
+
+The Modelverse State implements the data storage features of the Modelverse.
+To the Modelverse State, all data needs to be representable as a graph, which it will manipulate.
+
+All basic, and some composite, operations are implemented on this graph, such as creating nodes and edges, reading them, and deleting them.
+
+Modelverse Kernel (MvK)
+-----------------------
+
+The Modelverse Kernel communicates with the MvS and interprets its data.
+The Modelverse Kernel has no way of storing data, except by sending it to the MvS for storage.
+Through this architecture, the MvK becomes completely stateless and easily replacable.
+
+For the MvK, a set of rules is defined which tell it how to interpret the graph in the MvS.
+Complex programs can be written by encoding the program as a graph, and letting the MvK interpret it.
+
+To allow for maximal flexibility, the MvK can never expose the users to the internal identifier of the MvS, which the MvK uses.
+This allows the MvS to internally restructure itself without having to worry about stale references elsewhere.
+
+Modelverse Interface (MvI)
+--------------------------
+
+The Modelverse Interface is the part that most users will be using.
+It presents a textual or graphical interface to the Modelverse itself.
+Depending on the interface, the MvK and MvS will serve only as a repository (heavy client), or they serve as the tool itself (thin client).
+Either way, the communication is identical, just the granularity differs, and the place where the algorithms are implemented.
+
+Traditionally, the MvI is a compiler that compiles some code to either a graph, or operations for the MvK.
+This can, however, be any possible kind of tool, or even combination of multiple tools.
+For example, a graphical tool could serve as an interface to the Modelverse, where it just processes the graphical events and sends the desired operations (such as creating an element) to the Modelverse.

+ 469 - 0
doc/_build/html/_sources/examples.txt

@@ -0,0 +1,469 @@
+Examples
+========
+
+To run this code, store it in a file (*e.g.*, test.alc), and execute the following commands::
+
+    python scripts/run_local_modelverse.py 8001 &
+    python scripts/make_parallel.py http://localhost:8001 test test.alc bootstrap/primitives.alc
+    python scripts/prompt.py
+
+In the prompt, log on to http://localhost:8001 as user *test*.
+Now, all input you send, will be caught in the *input()* calls seen in the code.
+Results will also be printed.
+
+Note that all content will, by default, be typed as string.
+If you want to send integers or so, prepend the input with a backslash (\\), which allows you to directly input the JSON code.
+For example, input *5* will be received as the string "5".
+To send the integer 5, the input should be *\\5*.
+
+Fibonacci Server
+----------------
+
+The first example is a simple Fibonacci server.
+The code is identical to the action language example from before, as this already included the *server* part (*i.e.*, the while loop).
+Now we will just connect to it using *prompt.py* and try out the code directly.
+
+The code is repeated below::
+
+    include "primitives.alh"
+
+    Integer function fib(param : Integer):
+        if (param <= 2):
+            return 1!
+        else:
+            return fib(param - 1) + fib(param - 2)!
+
+    Void function main():
+        while(True):
+            output(fib(input()))
+
+To run this code, save it to a file (*e.g.*, fibonacci.alc) and execute the following command::
+
+    python scripts/run_local_modelverse.py 8001
+    
+Now, the Modelverse is running, but we still need to upload our code.
+To compile the file, together with the primitives.alc file, execute the following command::
+
+    python scripts/make_parallel.py http://localhost:8001 test fibonacci.alc bootstrap/primitives.alc
+
+When this finishes, the Modelverse now stores a copy of our code in its own format.
+The Modelverse will automatically create the user *test* and start executing the *main* function as this user.
+We can therefore simply connect to the Modelverse as the *test* user and start seeing the responses.
+To start the prompt, execute the following command::
+
+    python scripts/prompt.py
+    
+In this prompt tool, you first have to configure the location of the Modelverse and the username.
+The defaults should be fine, so just press <return> twice.
+After that, you are in direct connection with the Modelverse.
+Each message you type in, is made available in the *input()* function of the code.
+Remember that, to send integers, you have to prefix this with a backslash (\\).
+To get, for example, the 1st Fibonacci number, type in the command::
+
+    \1
+
+You will now see the following.
+
+.. image:: img/prompt_fibonacci.png
+
+Since we are in an unconditional loop, you can send as many requests as you want, as long as they are understandable by the *fib* function.
+
+.. image:: img/prompt_fibonacci_more.png
+
+Inputting a string directly, such as *1* instead of *\\1*, will make the Modelverse crash on the execution of this code.
+This is normal, though in the future the Modelverse will keep running for other users: only the current user's code will be interrupted.
+
+Modelling Server
+----------------
+
+The simple Fibonacci server is not very relevant to the primary concern of the Modelverse: (meta-)modelling.
+But since we can create whatever kind of server we want, a simple (meta-)modelling server is created.
+The code offers an interface for users to execute modelling operations.
+The interface itself mostly just relays the incoming messages and operations to the internal modelling library.
+
+The full code is seen below::
+
+    include "primitives.alh"
+    include "constructors.alh"
+    include "object_operations.alh"
+    include "library.alh"
+    include "conformance_scd.alh"
+    include "io.alh"
+    include "metamodels.alh"
+    include "modelling.alh"
+    include "compilation_manager.alh"
+
+    Element function model_loaded(model : Element):
+        String cmd
+
+        Element attr_list_pn
+        Element attr_keys_pn
+        String attr_key_pn
+        Element metamodel_element_pn
+        String typename
+        Boolean bottom
+        Element other_metamodel
+
+        bottom = False
+        other_metamodel = create_node()
+        dict_add(other_metamodel, "model", model["model"])
+        dict_add(other_metamodel, "type_mapping", create_node())
+        dict_add(other_metamodel, "metamodel", import_node("models/LTM_bottom"))
+        dict_add(other_metamodel, "inheritance", other_metamodel["metamodel"]["model"]["__Inheritance"])
+
+        output("Model loaded, ready for commands!")
+        output("Use 'help' command for a list of possible commands")
+
+        while (True):
+            output("Please give your command.")
+            cmd = input()
+            if (cmd == "help"):
+                output("Generic model operations:")
+                output("  instantiate -- Create a new model element")
+                output("  delete      -- Delete an existing element")
+                output("  attr_add    -- Add an attribute to an element")
+                output("  attr_del    -- Delete an attribute of an element")
+                output("  constrain   -- Add a constraint function to the model")
+                output("  rename      -- Rename an existing element")
+                output("  modify      -- Modify the attributes of an element")
+                output("  list        -- Prints the list of elements in the model")
+                output("  types       -- Prints the list of elements that can be instantiated")
+                output("  read        -- Prints the current state of a model element")
+                output("  verify      -- Check whether the model conforms to the metamodel")
+                output("  retype      -- Change the type of an element")
+                output("  switch      -- Switch between conformance bottom and the linguistic metamodel")
+                output("  exit        -- Unload the model and go back to the loading prompt")
+            elif (cmd == "exit"):
+                return model!
+            elif (cmd == "instantiate"):
+                String mm_type_name
+                output("Type to instantiate?")
+                mm_type_name = input()
+                if (dict_in(model["metamodel"]["model"], mm_type_name)):
+                    String element_name
+                    output("Name of new element?")
+                    element_name = input()
+                    if (dict_in(model["model"], element_name)):
+                        output("Element already exists; aborting")
+                    else:
+                        if (is_edge(model["metamodel"]["model"][mm_type_name])):
+                            output("Source name?")
+                            String src_name
+                            src_name = input()
+                            if (dict_in(model["model"], src_name)):
+                                output("Destination name?")
+                                String dst_name
+                                dst_name = input()
+                                if (dict_in(model["model"], dst_name)):
+                                    instantiate_link(model, mm_type_name, element_name, src_name, dst_name)
+                                    output("Instantiation successful!")
+                                else:
+                                    output("Unknown destination; aborting")
+                            else:
+                                output("Unknown source; aborting")
+                        else:
+                            instantiate_node(model, mm_type_name, element_name)
+                            output("Instantiation successful!")
+                else:
+                    output("Unknown type specified; aborting")
+            elif (cmd == "set_inheritance"):
+                String inh_name
+
+                output("Which link in the metamodel is the inheritance link?")
+                inh_name = input()
+
+                if (dict_in(model["metamodel"]["model"], inh_name)):
+                    dict_add(model, "inheritance", model["metamodel"]["model"][inh_name])
+                    output("Set inheritance link!")
+                else:
+                    output("Element not found in metamodel; aborting")
+
+            elif (cmd == "constrain"):
+                output("Element to constrain (empty for global)?")
+                String model_name
+                model_name = input()
+
+                if (model_name == ""):
+                    // Global constraint
+                    output("Give input to function constructors for GLOBAL constraint!")
+                    set_model_constraints(model, construct_function())
+                elif (dict_in(model["model"], model_name)):
+                    // Local constraint for this model
+                    output("Give input to function constructors for LOCAL constraint!")
+                    add_constraint(model, model_name, construct_function())
+                    output("Added constraint to model!")
+                else:
+                    // Local constraint, but model not found
+                    output("Unknown model; aborting")
+            elif (cmd == "modify"):
+                String model_name
+                output("Element to modify?")
+                model_name = input()
+                if (dict_in(model["model"], model_name)):
+                    Element attrs
+                    attrs = getAttributeList(model, model_name)
+                    String attr_name
+                    output("Attribute to modify?")
+                    attr_name = input()
+                    if (set_in(dict_keys(attrs), attr_name)):
+                        output("New value?")
+                        unset_attribute(model, model_name, attr_name)
+                        instantiate_attribute(model, model_name, attr_name, input())
+                        output("Modified!")
+                    else:
+                        output("No such attribute!")
+                else:
+                    output("No such model!")
+            elif (cmd == "attr_add"):
+                String model_name
+                output("Which model do you want to assign an attribute to?")
+                model_name = input()
+                if (dict_in(model["model"], model_name)):
+                    Element attrs
+                    attrs = getAttributeList(model, model_name)
+                    String attr_name
+                    output("Which attribute do you wish to assign?")
+                    attr_name = input()
+                    if (set_in(dict_keys(attrs), attr_name)):
+                        output("Value of attribute?")
+                        instantiate_attribute(model, model_name, attr_name, input())
+                        output("Added attribute!")
+                    else:
+                        output("No such attribute!")
+                else:
+                    output("No such model!")
+            elif (cmd == "attr_del"):
+                String model_name
+                output("Which model do you want to remove an attribute of?")
+                model_name = input()
+                if (dict_in(model["model"], model_name)):
+                    Element attrs
+                    attrs = getAttributeList(model, model_name)
+                    String attr_name
+                    output("Which attribute do you want to delete?")
+                    attr_name = input()
+                    if (set_in(dict_keys(attrs), attr_name)):
+                        unset_attribute(model, model_name, attr_name)
+                        output("Attribute deleted!")
+                    else:
+                        output("No such attribute!")
+                else:
+                    output("No such model!")
+            elif (cmd == "delete"):
+                output("What is the name of the element you want to delete?")
+                cmd = input()
+                if (dict_in(model["model"], cmd)):
+                    model_delete_element(model, cmd)
+                    output("Deleted!")
+                else:
+                    output("No such element; aborting")
+            elif (cmd == "rename"):
+                output("Old name?")
+                String old_name_e
+                old_name_e = input()
+                if (dict_in(model["model"], old_name_e)):
+                    output("New name?")
+                    String new_name_e
+                    new_name_e = input()
+                    if (dict_in(model["model"], new_name_e)):
+                        output("New name already used; aborting")
+                    else:
+                        dict_add(model["model"], new_name_e, model["model"][old_name_e])
+                        dict_delete(model["model"], old_name_e)
+                        output("Rename complete!")
+                else:
+                    output("Unknown element; aborting")
+            elif (cmd == "list"):
+                Element keys_m
+                keys_m = dict_keys(model["model"])
+                output("List of all elements:")
+                String v_m
+                while (read_nr_out(keys_m) > 0):
+                    v_m = set_pop(keys_m)
+                    // Filter out anonymous objects
+                    if (bool_not(string_startswith(v_m, "__"))):
+                        typename = reverseKeyLookup(model["metamodel"]["model"], dict_read_node(model["type_mapping"], model["model"][v_m]))
+                        output((("  " + v_m) + " : ") + typename)
+            elif (cmd == "read"):
+                output("Element to read?")
+                cmd = input()
+                if (dict_in(model["model"], cmd)):
+                    Element read_elem
+                    read_elem = model["model"][cmd]
+                    metamodel_element_pn = dict_read_node(model["type_mapping"], read_elem)
+
+                    output("Name: " + cmd)
+                    output("Type: " + reverseKeyLookup(model["metamodel"]["model"], metamodel_element_pn))
+                    if (is_edge(read_elem)):
+                        output("Source: " + reverseKeyLookup(model["model"], read_edge_src(read_elem)))
+                        output("Destination: " + reverseKeyLookup(model["model"], read_edge_dst(read_elem)))
+                    if (cast_v2s(read_elem) != "None"):
+                        output("Value: " + cast_v2s(read_elem))
+                    output("Defines attributes:")
+                    attr_list_pn = getInstantiatableAttributes(model, read_elem)
+                    attr_keys_pn = dict_keys(attr_list_pn)
+                    while (0 < read_nr_out(attr_keys_pn)):
+                        attr_key_pn = set_pop(attr_keys_pn)
+                        output(((("  " + attr_key_pn) + " : ") + cast_v2s(attr_list_pn[attr_key_pn])))
+                    output("Attributes:")
+                    attr_list_pn = getAttributeList(model, cmd)
+                    attr_keys_pn = dict_keys(attr_list_pn)
+                    while (0 < read_nr_out(attr_keys_pn)):
+                        attr_key_pn = set_pop(attr_keys_pn)
+                        output((((("  " + cast_v2s(attr_key_pn)) + " : ") + cast_v2s(attr_list_pn[attr_key_pn])) + " = ") + cast_v2s(read_attribute(model, reverseKeyLookup(model["model"], read_elem), attr_key_pn)))
+                else:
+                    output("Unknown element; aborting")
+            elif (cmd == "verify"):
+                output(conformance_scd(model))
+            elif (cmd == "types"):
+                Element keys_t
+                keys_t = dict_keys(model["metamodel"]["model"])
+                output("List of types:")
+                String v_t
+                while (read_nr_out(keys_t) > 0):
+                    v_t = set_pop(keys_t)
+                    if (bool_not(string_startswith(v_t, "__"))):
+                        output(string_join(("  " + v_t) + " : ", reverseKeyLookup(model["metamodel"]["metamodel"]["model"], dict_read_node(model["metamodel"]["type_mapping"], model["metamodel"]["model"][v_t]))))
+            elif (cmd == "retype"):
+                output("Element to retype?")
+                String elementname
+                elementname = input()
+                if (dict_in(model["model"], elementname)):
+                    output("New type")
+                    typename = input()
+                    if (dict_in(model["metamodel"]["model"], typename)):
+                        // OK, do the retyping
+                        // First try removing the previous type if it exists
+                        dict_delete(model["type_mapping"], model["model"][elementname])
+                        // Now add the new type
+                        dict_add(model["type_mapping"], model["model"][elementname], model["metamodel"]["model"][typename])
+                        output("Retyped!")
+                    else:
+                        output("Unknown type; aborting")
+                else:
+                    output("Unknown element; aborting")
+            elif (cmd == "switch"):
+                bottom = bool_not(bottom)
+
+                Element tmp_model
+                tmp_model = model
+                model = other_metamodel
+                other_metamodel = tmp_model
+
+                if (bottom):
+                    // The type mapping we are using is probably not complete for our model
+                    // so we completely recreate it from the model we have.
+                    output("Switching to conformance bottom mode!")
+                    generate_bottom_type_mapping(model)
+                else:
+                    // We already switched the models and such, so we are already done!
+                    output("Switching to linguistic metamodel!")
+            else:
+                output("Unknown command: " + cast_v2s(cmd))
+                output("Use command 'help' to get a list of available commands")
+
+    Element function main():
+        output("Welcome to the Model Management Interface, running live on the Modelverse!")
+        output("Use 'help' command for a list of possible commands")
+        String command
+        Element root
+        Element metamodel
+        String name
+        Element my_model
+        String mm_name
+
+        root = create_metamodels()
+
+        while (True):
+            output("Please give your command.")
+            command = input()
+
+            if (command == "help"):
+                output("Currently no model is loaded, so your operations are limited to:")
+                output("  new    -- Create a new model and save it for future use")
+                output("  load   -- Load a previously made model")
+                output("  rename -- Rename a previously made model")
+                output("  delete -- Delete a previously made model")
+                output("  list   -- Show a list of all stored models")
+                output("  help   -- Show a list of possible commands")
+            elif (command == "new"):
+                output("Metamodel to instantiate?")
+                mm_name = input()
+                if (dict_in(root, mm_name)):
+                    output("Name of model?")
+                    name = input()
+                    if (dict_in(root, name)):
+                        output("Model exists; aborting")
+                    else:
+                        my_model = instantiate_model(root[mm_name])
+                        dict_add(root, name, my_model)
+                        model_loaded(my_model)
+                else:
+                    output("Unknown metamodel; aborting")
+            elif (command == "load"):
+                output("Model to load?")
+                name = input()
+                if (dict_in(root, name)):
+                    my_model = root[name]
+                    model_loaded(my_model)
+                else:
+                    output("Model not found; aborting")
+            elif (command == "list"):
+                Element keys
+                String m_menu_list
+                keys = dict_keys(root)
+                output("Found models:")
+                while (read_nr_out(keys) > 0):
+                    m_menu_list = set_pop(keys)
+                    output((("  " + m_menu_list) + " : ") + reverseKeyLookup(root, root[m_menu_list]["metamodel"]))
+            elif (command == "delete"):
+                output("Model to delete?")
+                name = input()
+                if (dict_in(root, name)):
+                    dict_delete(root, name)
+                    output("Deleted!")
+                else:
+                    output("Model not found; aborting")
+            elif (command == "rename"):
+                output("Old name?")
+                String old_name
+                old_name = input()
+                if (dict_in(root, old_name)):
+                    output("New name?")
+                    String new_name
+                    new_name = input()
+                    if (dict_in(root, new_name)):
+                        output("Model exists; aborting")
+                    else:
+                        dict_add(root, new_name, root[old_name])
+                        dict_delete(root, old_name)
+                        output("Rename complete!")
+                else:
+                    output("Model not found; aborting")
+            elif (command == "actions"):
+                output("Switching to compilation manager!")
+                compilation_manager()
+                output("Back in model manager!")
+            else:
+                output("Command not recognized, use 'help' for a list of possible commands")
+
+This code implements a very simple (meta-)modelling tool.
+Its use is documented with the provided *help* function.
+A simple example of its use is shown below.
+
+.. image:: img/prompt_pn_interface.png
+
+In this case, note that the value of tokens is the string 3 instead of the integer (or natural) 3.
+Therefore, the conformance check will flag this value as incorrectly typed.
+
+Upload model
+------------
+
+Uploading a model, and using it, is very similar to what you usually do.
+The exception is that your model will be added before any code is executed.
+That way, you can just execute the same modelling server, but include a model in it.
+Doing that, your interface will see additional models with the *list* command.
+
+The command for this is (instead of the *make_all.py* script)::
+
+    python scripts/execute_model.py http://localhost:8001 test bootstrap/*.alc integration/code/pn_interface.alc integration/code/rpgame.mvc

+ 179 - 0
doc/_build/html/_sources/howto.txt

@@ -0,0 +1,179 @@
+How to run
+==========
+
+Running the Modelverse is all done through the use of scripts to coordinate the three different projects.
+
+The following scripts are included by default.
+
+check_objects.py
+----------------
+
+Checks whether all compiled objects can be found, and if their symbol table does not contain undefined references.
+This script cannot be executed directly and is only a helper.
+
+compile.py
+----------
+
+Compiles the provided code with the selected mode.
+This should also not be called by end-users, though it is possible.
+
+Invocation::
+
+    python scripts/compile.py address file username object mode
+
+============== ====================================== =====================
+Parameter name Description                            Example              
+============== ====================================== =====================
+address        Address of the Modelverse              http://localhost:8001
+file           File to be compiled                    file.alc             
+username       Username to use when compiling         test_user            
+object         Object name to export to               object.o             
+mode           Either CO (constructors) or PO (graph) PO                   
+============== ====================================== =====================
+
+execute_model.py
+----------------
+
+Compile a model and action language files together, executing the action language.
+First, all models are added, and then the action language is executed, starting at function "main".
+Models being created are temporary, so they need to be exported before they can be accessed in the action language.
+
+Invocation::
+
+    python scripts/execute_model.py address username file1 file2 ...
+
+============== ======================================= =====================
+Parameter name Description                             Example
+============== ======================================= =====================
+address        Address of the Modelverse               http://localhost:8001
+username       Username to use when compiling          test
+file           File to compile (either .mvc or .alc)   test.alc
+============== ======================================= =====================
+
+fix_files.py
+------------
+
+Fix some files that must be kept identical.
+This is sometimes necessary because if a file gets updated, the changes must propagate.
+Usually, this is done with symbolic links or similar, but there does not seem to be a nice cross-platform way of doing this in Git.
+
+Invocation::
+    
+    python scripts/fix_files.py
+
+flush_compiler_caches.py
+------------------------
+
+Clear all cached files from the compiler.
+The compiler will automatically reparse files when they have been changed, but changes to the compiler code itself will not be detected.
+When changing the compiler, this file should be executed to flush these file caches.
+
+Invocation::
+
+    python scripts/flush_compiler_caches.py
+
+generate_bootstrap.py
+---------------------
+
+Creates the bootstrap file for the Modelverse State.
+This creates the necessary initial graph which contains links to all primitive code that is executed by the Modelverse before users can communicate with it.
+Generally, this needs to be executed when any file in the *bootstrap/* folder is modified.
+Compilation is fairly smart, only recompiling parts that have changed.
+
+Invocation::
+    
+    python scripts/generate_bootstrap.py
+
+link_and_load.py
+----------------
+
+This takes a set of objects in the Modelverse, links them together in a single "executable" and executes it immediately.
+Generally not needed by end-users.
+
+Invocation::
+
+    python scripts/link_and_load.py address username object1 object2 ...
+
+============== ======================================= =====================
+Parameter name Description                             Example
+============== ======================================= =====================
+address        Address of the Modelverse               http://localhost:8001
+username       Username to use when compiling          test
+object         File to compile (either .mvc or .alc)   test.alc
+============== ======================================= =====================
+
+make_all.py
+-----------
+
+Compile a set of files and executes them immediately.
+This uses constructors by default, which is the most elegant, but also the slowest.
+
+Invocation::
+
+    python scripts/make_all.py address username file1 file2 ...
+
+============== ======================================= =====================
+Parameter name Description                             Example
+============== ======================================= =====================
+address        Address of the Modelverse               http://localhost:8001
+username       Username to use when compiling          test
+file           File to compile (either .mvc or .alc)   test.alc
+============== ======================================= =====================
+
+make_parallel.py
+----------------
+
+A parallel version of make_all.py.
+This uses the direct graph compilation, and compiles these graphs in parallel.
+This is much faster than make_all, though much less elegant.
+
+Invocation::
+
+    python scripts/make_parallel.py address username file1 file2 ...
+
+============== ======================================= =====================
+Parameter name Description                             Example
+============== ======================================= =====================
+address        Address of the Modelverse               http://localhost:8001
+username       Username to use when compiling          test
+file           File to compile (either .mvc or .alc)   test.alc
+============== ======================================= =====================
+
+prompt.py
+---------
+
+A generic prompt interface to the Modelverse.
+You can log in as a specific user and start sending input messages to the Modelverse as that user.
+All output sent by the Modelverse will be printed in the console.
+There is no logic in the prompt itself, making it completely generic.
+
+Invocation::
+
+    python scripts/prompt.py
+
+run_local_modelverse.py
+-----------------------
+
+Locally runs an instance of the Modelverse at the requested port.
+This combines MvK and MvS at the same system, and actually makes a direct link between them, omitting the slow use of sockets.
+While this is kind of a hack at the moment, it is really necessary with the current low performance.
+To split them up, there just needs to be a statechart in between both of them (which is already written and working).
+
+Invocation::
+
+    python scripts/run_local_modelverse.py port
+
+============== ============================== =======
+Parameter name Description                    Example
+============== ============================== =======
+port           Port to host the Modelverse on 8001
+============== ============================== =======
+
+run_tests.py
+------------
+
+Run the tests for all parts of the Modelverse.
+
+Invocation::
+
+    python scripts/run_tests.py

+ 24 - 0
doc/_build/html/_sources/index.txt

@@ -0,0 +1,24 @@
+.. Modelverse documentation master file, created by
+   sphinx-quickstart on Wed Oct  5 09:12:15 2016.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+Welcome to Modelverse's documentation!
+======================================
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+    
+   Installation <installation>
+   Modelverse components <components>
+   How to run <howto>
+   Action Language <actionlanguage>
+   Modelling Language <modellanguage>
+   Examples <examples>
+   Advanced examples <advanced>
+   Common problems and solutions <problems>
+   Internal workings <internal>
+   Interface <interface>
+   Network communication models <communication_models>

+ 72 - 0
doc/_build/html/_sources/installation.txt

@@ -0,0 +1,72 @@
+Installation
+============
+
+Dependencies
+------------
+
+The Modelverse reference implementation is relatively dependency-free.
+As its code is written in Python 2, a working Python 2.7 interpreter is necessary.
+
+To run the tests, this interpreter needs to have the `pytest <http://docs.pytest.org/en/latest/>`_ module installed.
+
+To run the statecharts, the `SCCD <https://msdl.uantwerpen.be/git/simon/SCCD>`_ module needs to be installed.
+
+Installation
+------------
+
+The Modelverse is merely a set of scripts, and there is no real installation present.
+As such, you will only have to download the source code and are ready to use the Modelverse.
+
+0. Install dependencies.
+1. Download the `Modelverse source code <https://msdl.uantwerpen.be/git/yentl/modelverse>`_.
+   For example using git::
+
+    git clone https://msdl.uantwerpen.be/git/yentl/modelverse
+
+   Or using your favorite HTTP download tool::
+
+    wget https://msdl.uantwerpen.be/git/yentl/modelverse/archive/master.zip
+    unzip master.zip
+2. That's it! You can now run the scripts in the *scripts/* directory using Python.
+
+Tests
+-----
+
+To make sure that everything is working correctly, you can execute the tests with the script *scripts/run_tests.sh*.
+This test file will execute tests in parallel, using as many cores as it can.
+Nonetheless, total execution time is still rather slow (e.g., 1200 seconds on a i5-4570 using PyPy).
+
+Executing the tests is as simple as the following command::
+
+    python scripts/run_tests.py
+
+This will run a set of tests for all different projects.
+
+PyPy
+^^^^
+
+The default way of executing tests is probably through CPython.
+Note, however, that CPython is a very slow implementation of Python, which makes everything in the Modelverse slower.
+While it is not impossible to use CPython, using PyPy is highly recommended at the moment!
+Nonetheless, PyPy is often not the default interpretter present on the system.
+You will therefore have to explicitly give control to PyPy instead of CPython.
+
+This is fairly simple: all scripts in *scripts/* execute their subprocesses using the Python interpreter used to start the script.
+As such, the following command suffices to execute the Modelverse tests using PyPy::
+
+    pypy scripts/run_tests.py
+
+The problem, however, is that all modules need to be readily installed on PyPy.
+For SCCD, you can simply install it using PyPy instead of CPython.
+For pytest, you also need to install all of pytest's dependencies.
+The easiest way to do this is through *pip*, which you also have to install first::
+
+    wget https://bootstrap.pypa.io/get-pip.py
+    pypy get-pip.py --user
+    pypy -m pip install pytest --user
+
+Afterwards, you can simply run::
+
+    pypy scripts/run_tests.py
+
+To execute the tests using PyPy.

+ 98 - 0
doc/_build/html/_sources/interface.txt

@@ -0,0 +1,98 @@
+Interface description
+=====================
+
+All Modelverse components communicate with each other through the use of sockets.
+On these sockets, XML/HTTP Requests are used for communication.
+In this brief section, we describe the form of these requests.
+
+MvS server
+----------
+
+The MvS server listens to a fixed set of commands.
+All commands have a fully defined signature and result.
+Note that commands are encoded: a decoding table is presented below.
+
+==== ======================
+Code Description
+==== ======================
+CN   create_node
+CE   create_edge
+CNV  create_nodevalue
+CD   create_dict
+RV   read_value
+RO   read_outgoing
+RI   read_incoming
+RE   read_edge
+RD   read_dict
+RDN  read_dict_node
+RDNE read_dict_node_edge
+RDE  read_dict_edge
+RRD  read_reverse_dict
+RR   read_root
+RDK  read_dict_keys
+DE   delete_edge
+DN   delete_node
+==== ======================
+
+Requests are sent as POST requests (*i.e.*, in the data of a HTTP request).
+They have the following form::
+
+    op=CODE&params=PARAMS
+
+In this case, *CODE* is one of the codes mentioned above, and the value of *PARAMS* is a JSON encoded list of Modelverse identifiers.
+The choice of what is a Modelverse identifier is left to the MvS itself.
+
+The result will be a JSON serialized list containing as first element the response to the request, and as second element the statuscode.
+If the statuscode is 200, the first element will be correct.
+Otherwise, the statuscode indicates the error, and the first element is set to *null*.
+
+MvK server
+----------
+
+The communication with the MvK is a lot easier, as there is only a very minimal interface: the actual interface needs to be explicitly modelled in action language.
+Requests have the following form::
+
+    op=OPERATION&username=USERNAME&value=VALUE
+
+Here, *OPERATION* defines the operation to execute, of which only two exist:
+
+1. *set_input*, which adds the sent value to the input queue of the user;
+2. *get_output*, which blocks until there is a value in the output queue of the user.
+
+Obviously, *USERNAME* specifies the name of the user for which the operation needs to happen.
+
+The *VALUE* is just a JSON encoded value which will be added to the input queue of the Modelverse.
+This is ignored when the *get_output* operation is used.
+Note that there are some minor differences between our encoding and JSON encoding.
+
+The supported types are shown below.
+
+======= ===================
+Type    Example
+======= ===================
+Integer 1
+Float   1.0
+Boolean true
+String  "abc"
+Action  if
+======= ===================
+
+While this list mostly resembles JSON, there are some important differences:
+
+* Lists and objects are not supported;
+* Null object is not supported;
+* Action type is new, and contains a string representation (without quotes!) of the action language construct to add
+
+As response, the *set_input* will always receive the same reply if the message was correctly deserialized.
+Receiving a reply does *NOT* mean that a message was consumed by the user, it only means that the message was correctly added to the input queue of that user.
+
+A *get_output* request blocks until a value is available in the users output queue.
+The reply to this message will then contain a JSON serialized (with identical remarks as for *set_input*) containing the value that was output.
+Note that now the *null* message is possible, in case the node that is being outputted does not contain a value (or is an edge).
+
+Performance notes
+^^^^^^^^^^^^^^^^^
+
+For performance reasons, sending a huge amount of data to the Modelverse (*e.g.*, a compiled program), should not happen with individual requests for each line.
+To allow for packed messages, users can ignore the *value* parameter, and use the *data* parameter instead.
+The content of this parameter should be a JSON encoded list of all individual values to be inserted.

+ 218 - 0
doc/_build/html/_sources/internal.txt

@@ -0,0 +1,218 @@
+Internal workings
+=================
+
+For more detailed information on the Modelverse specification, which this project is implementing, we refer to the `Modelverse Specification <http://msdl.cs.mcgill.ca/people/yentl/files/Modelverse.pdf>`_.
+
+Information on the implementation can be found below.
+
+Modelverse State
+----------------
+
+The Modelverse State is basically just an implementation of a graph library.
+As we have a particular kind of graph, this implementation is mostly done by hand at the moment.
+The notable exception to this is the RDF backend, proving that other implementations can also be used.
+
+The basic implementation just stores everything as dictionaries.
+All operations are then defined by doing operations on these dictionaries.
+The most interesting operations here are dictionary operations, which need to traverse these dictionaries in complex ways.
+To overcome performance problems for these operations, all results are cached (and validated afterwards).
+
+RDF backend
+^^^^^^^^^^^
+
+The RDF backend requires the *rdflib* module in Python.
+The Modelverse graph is then stored in RDF representation and all operations on it are done using SPARQL queries.
+Due to this level of indirection, performance is extremely slow.
+To increase performance, we would likely have to make more *composite* operations, or even group different requests together internally.
+
+Status codes
+^^^^^^^^^^^^
+
+The MvS returns, apart from its actual return value, a status code for the request.
+This value is not used by the MvK at all, since sometimes a request is expected to give an error (*e.g.*, checking whether an element is present).
+When debugging the MvS, however, these status codes can come in handy.
+
+Modelverse Kernel
+-----------------
+
+The Modelverse Kernel is basically a graph transformation kernel.
+It consists of two parts: a small transformation engine (only a few lines in Python), and a copy of all rules it knows.
+Most code is an encoding of these transformation rules, and can (theoretically) be automatically generated by the Modelverse itself.
+This is currently not top priority, but will probably be implemented in the future.
+
+The transformation rules are an encoding of the rules presented in the specification mentioned at the top of this page.
+In each rule, the MvK needs to have tight communication with the MvS.
+For this, the rules are encoded using *yield* operations in Python.
+Rules therefore act as generators, outputting commands to the MvS, and immediately getting a reply.
+Each individual yield contains a list of operations to send to the MvS simultaneously.
+The result will therefore also be a list of results for each operation.
+
+As you can see in these rules, each entry in the list has a specific form.
+An entry is a tuple containing two elements: the code of the operation to execute, followed by a list of all parameters to pass.
+The code is a shortened name for the operation, such as *CN* for *create_node*.
+A full mapping can be found in the MvS, the most important ones are shown below.
+
+==== ================
+Code Function
+==== ================
+CN   create_node
+CNV  create_nodevalue
+CE   create_edge
+CD   create_dict
+RV   read_value
+RE   read_edge
+RD   read_dict
+RDN  read_dict_node
+DN   delete_node
+DE   delete_edge
+==== ================
+
+.. note::
+   Since each yield operation works on lists even a single operation needs to be wrapped in a list.
+   Worse, however, is that the return value will also be a list.
+   Instead of having to take the first element each time, Python allows you to write a comma after the variable, to make it expand it automatically.
+   Your syntax thus becomes::
+
+    a, = yield [("CN", [])]
+
+   Where a will now already contain the created node, and not a list with as first (and only) element the created node.
+
+
+Primitives
+^^^^^^^^^^
+
+The Modelverse Kernel also defines the primitives users can use.
+Primitives are necessary since we can't go deeper at some point.
+It is the MvK's responsibility to implement each and every primitive defined in the bootstrap file.
+
+Primitives are implemented in the bootstrap file as having a body with an empty node.
+When execution goes to this node, the MvK must execute the associated primitive instead.
+To do this, the MvK must map all these nodes to their corresponding primitive implementation during startup.
+
+Precompiled functions
+^^^^^^^^^^^^^^^^^^^^^
+
+Similar to primitives, the MvK also supports precompiled functions.
+A precompiled function is similar to a primitive in terms of implementation, but they do also have an implementation inside of the Modelverse itself.
+This means that there are two implementations: one hardcoded, and one in action language.
+Both should obviously be consistent.
+
+Whereas primitives are required for a functional Modelverse, precompiled functions are only a performance optimization, and can be disabled by the user for debugging purposes.
+This is interesting, since with precompiled functions, no intermediate values will be visible.
+Additionally, precompiled functions cannot be changed, as they are Python code instead of being explicitly modelled.
+
+Modelverse Interface
+--------------------
+
+Finally, we come to the Modelverse Interface.
+For the moment, this is only a simple compiler that takes action language or model language files and translates them to something the Modelverse can understand.
+There are basically two kinds of operations the Modelverse can understand: direct graphs, or a list of constructors.
+The use of direct graphs is deprecated, as constructors are much more elegant (but slower).
+Future changes should make constructors as fast as the use of graphs.
+Nonetheless, which approach is used does not matter for the action language or model language files.
+
+The parser used for this simple front-end is the HUTN parser.
+It creates an abstract syntax tree, which is then traversed by a series of visitors.
+The visitors that are used, depends on the selected mode of compilation.
+We briefly present the most important visitors.
+
+Semantics visitor
+^^^^^^^^^^^^^^^^^
+
+The visitor most oftenly used is the Semantics visitor.
+It traverses the abstract syntax tree and constructs symbol tables and finds all declarations of functions.
+Additionally, it also translates the use of operators to their Modelverse functions.
+
+This visitor in itself does not output anything, but it modifies the existing abstract syntax tree.
+It is used as a first step for most other visitors.
+
+Constructors visitor
+^^^^^^^^^^^^^^^^^^^^
+
+The most important visitor is the constructors visitor.
+It traverses the abstract syntax tree and outputs a list of strings that make it possible for the MvK to construct the required code in the Modelverse.
+The use of constructors has several advantages, but the primary advantage is that the interface does not have to know about the internal representation of action language in the Modelverse.
+However, the order of constructors and accepted keywords needs to be defined (in action language), and made available to the users.
+As this interface is explicitly modelled as well, it is possible for users to modify it without affecting the interface.
+This is bad if the interface suddenly accepts new keywords or removes support for old keywords.
+
+During the execution of the visitor, it would already be possible to start transmitting the list to the Modelverse, such that the Modelverse can create the code in parallel with the actual parsing.
+While this is possible, we currently split this up in different phases: first the list is generated completely, and then it is transferred to the Modelverse in a single request.
+
+Primitives visitor
+^^^^^^^^^^^^^^^^^^
+
+The primitives visitor generates a Modelverse graph directly.
+Its use is deprecated, as the constructors are much more elegant.
+While direct use of this visitor is not recommended, except for performance reasons, the bootstrap visitor (discussed next) is based on this visitor.
+
+This visitor creates a serialized version of the graph and transmits it to the Modelverse.
+The Modelverse has a built-in primitive to decode this graph and store it.
+
+Bootstrap visitor
+^^^^^^^^^^^^^^^^^
+
+Despite the primitives visitor being deprecated, the bootstrap visitor still needs access to this kind of output, since it cannot use constructors: during bootstrapping, the Modelverse is not yet available.
+The actual output format slightly differs from the primitives visitor, but the core concepts are identical.
+
+Model visitor
+^^^^^^^^^^^^^
+
+Finally, the model visitor is similar to the constructor visitor, but goes to a different constructor interface, which supports modelling operations instead of action language operations.
+This is a very preliminary visitor.
+
+Bootstrapping
+-------------
+
+To bootstrap, you just have to run the file *bootstrap.py*.
+Here, we explain what this file actually does...
+
+The bootstrap script primarily creates the initial graph manually.
+This manual creation is done by writing data to a file, which is later read by the MvS.
+The initial graph consists of several parts:
+
+* The Modelverse Root node;
+* A global definition of all primitives;
+* The stack frame of the initial user *user_manager*, which manages all other users;
+* The code for the *user_manager* user;
+* The code for all new users, as assigned by the *user_manager*;
+* Bindings in the compilation manager for bootstrap files.
+
+These are all fairly simple in themselves.
+For some parts, such as the code, the HUTN compiler is invoked on a temporary piece of code.
+All bootstrap files are also compiled and made available to the compilation manager with their MD5 hash.
+
+How to add a primitive
+----------------------
+
+Probably the most important reason why you would want to know about the Modelverse internals, is if you want to add a Modelverse primitive.
+Primitives are functions implemented in the MvK core, and thus become hardcoded.
+
+.. warning::
+    While these functions are hardcoded, their implementation needs to follow strict rules, such that their semantics is identical in all possible programming languages.
+    For example, a primitive *getTime()* cannot simply be implemented as *time.time()* in Python, as this gives different results on Linux and Windows.
+
+To add a primitive, follow these steps:
+
+1. Add the code of the primitive to the MvK implementation by adding it in the file *primitives.py*.
+
+    a. Name the function identically to how the primitive will be invoked later on.
+    b. Take a set of parameters. Parameters for primitives are always positional and start from *a* onwards.
+    c. The final parameter should be a catch-all element, as it is possible that a high number of additional information is passed. In Python, this is done with a parameter prepended with \*\*.
+    d. When asking the MvS for information, use yields, just like the implementation of transformation rules in the MvK.
+    e. Instead of return, use a *raise* with the exception *PrimitiveFinished*. This exception takes one argument: the returnvalue.
+
+2. Add the signature to *bootstrap.py* in the topmost dictionary *primitives*. The key is the name of the function, and the value is a list starting with the return type, followed by all parameter types (as string).
+3. Add the declaration to *includes/primitives.alh* to make them available everywhere.
+4. Add the definition to *primitives.alc* and assign the Modelverse reference *?primitives/function_name*.
+5. Recreate the bootstrap file by running the script *generate_bootstrap.py*.
+6. Restart the Modelverse to reload the bootstrap file.
+7. From now on, all files including *primitives.alh* have access to the defined function.
+
+Adding a precompiled function
+-----------------------------
+
+Adding a precompiled function is way easier: only step 1 of the addition of a primitive should be done, but in the file *compiled.py* instead of *primitives.py*.
+All other steps are done automatically since there is an action language implementation present.
+The MvK will then automatically pick the precompiled function or the explicitly modelled operation, depending on preferences.
+A restart of the MvK is needed for Python to pick up the new functions.

+ 174 - 0
doc/_build/html/_sources/modellanguage.txt

@@ -0,0 +1,174 @@
+Modelling Language
+==================
+
+Apart from the action language, the Modelverse also has a modelling language.
+With this language, models (*i.e.*, data) can be defined in addition to the algorithms.
+
+This language is still mostly work in progress, but should be decent enough to construct simple metamodels and instantiate them.
+All models have the extension \*.mvc, indicating that they are models and should be compiled as such.
+
+Language description
+--------------------
+
+The modelling language defines data structures, which will be formed as models in the Modelverse.
+
+Several constructs are supported.
+
+Import
+^^^^^^
+
+An import pulls in a model and makes it accessible using a simpler identifier.
+The structure is as follows::
+
+    import path/in/modelverse as my_model
+
+After this import, the model that was previously exported to *path/in/modelverse* becomes available as *my_model*.
+
+Include
+^^^^^^^
+
+When combined with action language, the action language might require some includes of header files.
+To do this, the includes can be placed at the top of the hierarchy.
+
+Model
+^^^^^
+
+Every model is defined by first specifying the type of model to instantiate, followed by the name of the model to create.
+The name of the model can then later on be referenced in other models (as type, or for exporting).
+Within the model, all names of the type model can be used as types again.
+
+Instance
+^^^^^^^^
+
+A model consists of some instances.
+These instances are instances of types specified by the model that is the metaclass of the current model.
+
+Attribute
+^^^^^^^^^
+
+Each model instance can contain attributes.
+There are two kinds of attributes: defining attributes, or value attributes.
+
+For defining attributes, the structure is as follows::
+
+    Class A{
+        my_parameter : ParameterType
+    }
+
+This defines a parameter called *my_parameter* which is typed by *ParameterType*.
+*ParameterType* must always be a type defined in the type that is being instantiated.
+Even if this is a primitive, such as *Integer*, the metamodel must define what it calls an *Integer*.
+While this might seem bothersome, this clearly defines the notion of what a type means, without having to resort to the implementation.
+
+Value attributes are similar, but have a different syntax, and contain an actual value.
+Their structure is as follows::
+
+    A a{
+        my_parameter = 1
+    }
+
+They assign a value to a previously defined attribute.
+In this case, it is important that the value conforms to the type specified in the defining attribute.
+
+Merge with Action Language
+--------------------------
+
+It is of course possible to incorporate action language inside of a model.
+A typical use case for this is the definition of constraints or actions.
+Action language is surrounded by dollar signs ($), which causes the parser to redirect the text between dollar signs to the action language parser.
+All includes necessary for the compilation of the action code, must be provided at the top of the document.
+
+Examples
+--------
+
+Some simple examples of models are provided below.
+This code only makes the specified models available in code; to do something with these models, an algorithms has to read out the model and operate on it.
+
+Petri Net metamodel
+^^^^^^^^^^^^^^^^^^^
+
+A simple Petri Net metamodel can be created, based on the SimpleClassDiagrams metamodel.
+This looks like this::
+
+    import models/SimpleClassDiagrams as SCD
+
+    SCD PetriNets{
+        Class Natural {}
+        Class Place{
+            tokens : Natural
+        }
+        Class Transition{}
+        Association P2T (Place, Transition) {
+            weight : Natural
+        }
+        Association T2P (Transition, Place) {
+            weight : Natural
+        }
+    }
+
+    export PetriNets to models/PetriNets
+
+Note that in this metamodel, there is no constraint placed on the value of a Natural: it can literaly be anything.
+That is why usually, you want to place constraints on the value.
+In this case, the value needs to be an integer, and it must be larger than or equal to zero.
+Such constraints are written in the action language, surrounded by dollar signs::
+
+    import models/SimpleClassDiagrams as SCD
+    include "primitives.alh"
+
+    SCD PetriNets{
+        Class Natural {
+            $
+                if (bool_not(is_physical_int(self))):
+                    return "Natural has no integer value at " + name!
+                elif (integer_lt(self, 0)):
+                    return "Natural does not have a positive or zero value at " + name!
+                else:
+                    return "OK"!
+             $
+        }
+        Class Place{
+            tokens : Natural {
+                target_lower_cardinality = 1
+                target_upper_cardinality = 1
+                }
+        }
+        Class Transition{}
+        Association P2T (Place, Transition) {
+            weight : Natural {
+                target_lower_cardinality = 1
+                target_upper_cardinality = 1
+                }
+        }
+        Association T2P (Transition, Place) {
+            weight : Natural {
+                target_lower_cardinality = 1
+                target_upper_cardinality = 1
+                }
+        }
+    }
+
+Petri Net instance
+^^^^^^^^^^^^^^^^^^
+
+The previous metamodel can then be instantiated::
+
+    import models/PetriNets as PetriNets
+
+    PetriNets my_petrinet {
+        Place p1 {
+            tokens = 1
+        }
+        Place p2 {
+            tokens = 3
+        }
+        Transition t1 {}
+        P2T (p1, t1) {
+            weight = 1
+        }
+        T2P (t1, p2) {
+            weight = 2
+        }
+    }
+
+    export my_petrinet to models/my_petrinet

+ 20 - 0
doc/_build/html/_sources/models.txt

@@ -0,0 +1,20 @@
+Network interface
+=================
+
+The network communication in the Modelverse builds on top of the raw socket implementation of Python.
+Whereas we use normal HTTP requests, we explicitly opted not to use these libraries.
+Many of these libraries hide important implementation details, such as how successive requests are handled (sequential, threaded, ...), whether or not to keep connections open and reuse them, which HTTP version to implement, and so on.
+As the HTTP protocol is a simple protocol, we reimplemented it completely in SCCD (StateCharts and Class Diagrams).
+
+There are two network components: a server in the MvS, and a server and client in the MvK.
+These are discussed next.
+
+MvS server
+----------
+
+.. image:: img/mvs_server.svg
+
+MvK server
+----------
+
+.. image:: img/mvk_server.svg

+ 2 - 0
doc/_build/html/_sources/problems.txt

@@ -0,0 +1,2 @@
+Common problems and solutions
+=============================

BIN
doc/_build/html/_static/ajax-loader.gif


+ 693 - 0
doc/_build/html/_static/alabaster.css

@@ -0,0 +1,693 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+@import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+    font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif;
+    font-size: 17px;
+    background-color: #fff;
+    color: #000;
+    margin: 0;
+    padding: 0;
+}
+
+
+div.document {
+    width: 940px;
+    margin: 30px auto 0 auto;
+}
+
+div.documentwrapper {
+    float: left;
+    width: 100%;
+}
+
+div.bodywrapper {
+    margin: 0 0 0 220px;
+}
+
+div.sphinxsidebar {
+    width: 220px;
+    font-size: 14px;
+    line-height: 1.5;
+}
+
+hr {
+    border: 1px solid #B1B4B6;
+}
+
+div.body {
+    background-color: #fff;
+    color: #3E4349;
+    padding: 0 30px 0 30px;
+}
+
+div.body > .section {
+    text-align: left;
+}
+
+div.footer {
+    width: 940px;
+    margin: 20px auto 30px auto;
+    font-size: 14px;
+    color: #888;
+    text-align: right;
+}
+
+div.footer a {
+    color: #888;
+}
+
+p.caption {
+    font-family: inherit;
+    font-size: inherit;
+}
+
+
+div.relations {
+    display: none;
+}
+
+
+div.sphinxsidebar a {
+    color: #444;
+    text-decoration: none;
+    border-bottom: 1px dotted #999;
+}
+
+div.sphinxsidebar a:hover {
+    border-bottom: 1px solid #999;
+}
+
+div.sphinxsidebarwrapper {
+    padding: 18px 10px;
+}
+
+div.sphinxsidebarwrapper p.logo {
+    padding: 0;
+    margin: -10px 0 0 0px;
+    text-align: center;
+}
+
+div.sphinxsidebarwrapper h1.logo {
+    margin-top: -10px;
+    text-align: center;
+    margin-bottom: 5px;
+    text-align: left;
+}
+
+div.sphinxsidebarwrapper h1.logo-name {
+    margin-top: 0px;
+}
+
+div.sphinxsidebarwrapper p.blurb {
+    margin-top: 0;
+    font-style: normal;
+}
+
+div.sphinxsidebar h3,
+div.sphinxsidebar h4 {
+    font-family: 'Garamond', 'Georgia', serif;
+    color: #444;
+    font-size: 24px;
+    font-weight: normal;
+    margin: 0 0 5px 0;
+    padding: 0;
+}
+
+div.sphinxsidebar h4 {
+    font-size: 20px;
+}
+
+div.sphinxsidebar h3 a {
+    color: #444;
+}
+
+div.sphinxsidebar p.logo a,
+div.sphinxsidebar h3 a,
+div.sphinxsidebar p.logo a:hover,
+div.sphinxsidebar h3 a:hover {
+    border: none;
+}
+
+div.sphinxsidebar p {
+    color: #555;
+    margin: 10px 0;
+}
+
+div.sphinxsidebar ul {
+    margin: 10px 0;
+    padding: 0;
+    color: #000;
+}
+
+div.sphinxsidebar ul li.toctree-l1 > a {
+    font-size: 120%;
+}
+
+div.sphinxsidebar ul li.toctree-l2 > a {
+    font-size: 110%;
+}
+
+div.sphinxsidebar input {
+    border: 1px solid #CCC;
+    font-family: 'goudy old style', 'minion pro', 'bell mt', Georgia, 'Hiragino Mincho Pro', serif;
+    font-size: 1em;
+}
+
+div.sphinxsidebar hr {
+    border: none;
+    height: 1px;
+    color: #AAA;
+    background: #AAA;
+
+    text-align: left;
+    margin-left: 0;
+    width: 50%;
+}
+
+/* -- body styles ----------------------------------------------------------- */
+
+a {
+    color: #004B6B;
+    text-decoration: underline;
+}
+
+a:hover {
+    color: #6D4100;
+    text-decoration: underline;
+}
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+    font-family: 'Garamond', 'Georgia', serif;
+    font-weight: normal;
+    margin: 30px 0px 10px 0px;
+    padding: 0;
+}
+
+div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
+div.body h2 { font-size: 180%; }
+div.body h3 { font-size: 150%; }
+div.body h4 { font-size: 130%; }
+div.body h5 { font-size: 100%; }
+div.body h6 { font-size: 100%; }
+
+a.headerlink {
+    color: #DDD;
+    padding: 0 4px;
+    text-decoration: none;
+}
+
+a.headerlink:hover {
+    color: #444;
+    background: #EAEAEA;
+}
+
+div.body p, div.body dd, div.body li {
+    line-height: 1.4em;
+}
+
+div.admonition {
+    margin: 20px 0px;
+    padding: 10px 30px;
+    background-color: #EEE;
+    border: 1px solid #CCC;
+}
+
+div.admonition tt.xref, div.admonition code.xref, div.admonition a tt {
+    background-color: ;
+    border-bottom: 1px solid #fafafa;
+}
+
+dd div.admonition {
+    margin-left: -60px;
+    padding-left: 60px;
+}
+
+div.admonition p.admonition-title {
+    font-family: 'Garamond', 'Georgia', serif;
+    font-weight: normal;
+    font-size: 24px;
+    margin: 0 0 10px 0;
+    padding: 0;
+    line-height: 1;
+}
+
+div.admonition p.last {
+    margin-bottom: 0;
+}
+
+div.highlight {
+    background-color: #fff;
+}
+
+dt:target, .highlight {
+    background: #FAF3E8;
+}
+
+div.warning {
+    background-color: #FCC;
+    border: 1px solid #FAA;
+}
+
+div.danger {
+    background-color: #FCC;
+    border: 1px solid #FAA;
+    -moz-box-shadow: 2px 2px 4px #D52C2C;
+    -webkit-box-shadow: 2px 2px 4px #D52C2C;
+    box-shadow: 2px 2px 4px #D52C2C;
+}
+
+div.error {
+    background-color: #FCC;
+    border: 1px solid #FAA;
+    -moz-box-shadow: 2px 2px 4px #D52C2C;
+    -webkit-box-shadow: 2px 2px 4px #D52C2C;
+    box-shadow: 2px 2px 4px #D52C2C;
+}
+
+div.caution {
+    background-color: #FCC;
+    border: 1px solid #FAA;
+}
+
+div.attention {
+    background-color: #FCC;
+    border: 1px solid #FAA;
+}
+
+div.important {
+    background-color: #EEE;
+    border: 1px solid #CCC;
+}
+
+div.note {
+    background-color: #EEE;
+    border: 1px solid #CCC;
+}
+
+div.tip {
+    background-color: #EEE;
+    border: 1px solid #CCC;
+}
+
+div.hint {
+    background-color: #EEE;
+    border: 1px solid #CCC;
+}
+
+div.seealso {
+    background-color: #EEE;
+    border: 1px solid #CCC;
+}
+
+div.topic {
+    background-color: #EEE;
+}
+
+p.admonition-title {
+    display: inline;
+}
+
+p.admonition-title:after {
+    content: ":";
+}
+
+pre, tt, code {
+    font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
+    font-size: 0.9em;
+}
+
+.hll {
+    background-color: #FFC;
+    margin: 0 -12px;
+    padding: 0 12px;
+    display: block;
+}
+
+img.screenshot {
+}
+
+tt.descname, tt.descclassname, code.descname, code.descclassname {
+    font-size: 0.95em;
+}
+
+tt.descname, code.descname {
+    padding-right: 0.08em;
+}
+
+img.screenshot {
+    -moz-box-shadow: 2px 2px 4px #EEE;
+    -webkit-box-shadow: 2px 2px 4px #EEE;
+    box-shadow: 2px 2px 4px #EEE;
+}
+
+table.docutils {
+    border: 1px solid #888;
+    -moz-box-shadow: 2px 2px 4px #EEE;
+    -webkit-box-shadow: 2px 2px 4px #EEE;
+    box-shadow: 2px 2px 4px #EEE;
+}
+
+table.docutils td, table.docutils th {
+    border: 1px solid #888;
+    padding: 0.25em 0.7em;
+}
+
+table.field-list, table.footnote {
+    border: none;
+    -moz-box-shadow: none;
+    -webkit-box-shadow: none;
+    box-shadow: none;
+}
+
+table.footnote {
+    margin: 15px 0;
+    width: 100%;
+    border: 1px solid #EEE;
+    background: #FDFDFD;
+    font-size: 0.9em;
+}
+
+table.footnote + table.footnote {
+    margin-top: -15px;
+    border-top: none;
+}
+
+table.field-list th {
+    padding: 0 0.8em 0 0;
+}
+
+table.field-list td {
+    padding: 0;
+}
+
+table.field-list p {
+    margin-bottom: 0.8em;
+}
+
+table.footnote td.label {
+    width: .1px;
+    padding: 0.3em 0 0.3em 0.5em;
+}
+
+table.footnote td {
+    padding: 0.3em 0.5em;
+}
+
+dl {
+    margin: 0;
+    padding: 0;
+}
+
+dl dd {
+    margin-left: 30px;
+}
+
+blockquote {
+    margin: 0 0 0 30px;
+    padding: 0;
+}
+
+ul, ol {
+    /* Matches the 30px from the narrow-screen "li > ul" selector below */
+    margin: 10px 0 10px 30px;
+    padding: 0;
+}
+
+pre {
+    background: #EEE;
+    padding: 7px 30px;
+    margin: 15px 0px;
+    line-height: 1.3em;
+}
+
+div.viewcode-block:target {
+    background: #ffd;
+}
+
+dl pre, blockquote pre, li pre {
+    margin-left: 0;
+    padding-left: 30px;
+}
+
+dl dl pre {
+    margin-left: -90px;
+    padding-left: 90px;
+}
+
+tt, code {
+    background-color: #ecf0f3;
+    color: #222;
+    /* padding: 1px 2px; */
+}
+
+tt.xref, code.xref, a tt {
+    background-color: #FBFBFB;
+    border-bottom: 1px solid #fff;
+}
+
+a.reference {
+    text-decoration: none;
+    border-bottom: 1px dotted #004B6B;
+}
+
+/* Don't put an underline on images */
+a.image-reference, a.image-reference:hover {
+    border-bottom: none;
+}
+
+a.reference:hover {
+    border-bottom: 1px solid #6D4100;
+}
+
+a.footnote-reference {
+    text-decoration: none;
+    font-size: 0.7em;
+    vertical-align: top;
+    border-bottom: 1px dotted #004B6B;
+}
+
+a.footnote-reference:hover {
+    border-bottom: 1px solid #6D4100;
+}
+
+a:hover tt, a:hover code {
+    background: #EEE;
+}
+
+
+@media screen and (max-width: 870px) {
+
+    div.sphinxsidebar {
+    	display: none;
+    }
+
+    div.document {
+       width: 100%;
+
+    }
+
+    div.documentwrapper {
+    	margin-left: 0;
+    	margin-top: 0;
+    	margin-right: 0;
+    	margin-bottom: 0;
+    }
+
+    div.bodywrapper {
+    	margin-top: 0;
+    	margin-right: 0;
+    	margin-bottom: 0;
+    	margin-left: 0;
+    }
+
+    ul {
+    	margin-left: 0;
+    }
+
+	li > ul {
+        /* Matches the 30px from the "ul, ol" selector above */
+		margin-left: 30px;
+	}
+
+    .document {
+    	width: auto;
+    }
+
+    .footer {
+    	width: auto;
+    }
+
+    .bodywrapper {
+    	margin: 0;
+    }
+
+    .footer {
+    	width: auto;
+    }
+
+    .github {
+        display: none;
+    }
+
+
+
+}
+
+
+
+@media screen and (max-width: 875px) {
+
+    body {
+        margin: 0;
+        padding: 20px 30px;
+    }
+
+    div.documentwrapper {
+        float: none;
+        background: #fff;
+    }
+
+    div.sphinxsidebar {
+        display: block;
+        float: none;
+        width: 102.5%;
+        margin: 50px -30px -20px -30px;
+        padding: 10px 20px;
+        background: #333;
+        color: #FFF;
+    }
+
+    div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p,
+    div.sphinxsidebar h3 a {
+        color: #fff;
+    }
+
+    div.sphinxsidebar a {
+        color: #AAA;
+    }
+
+    div.sphinxsidebar p.logo {
+        display: none;
+    }
+
+    div.document {
+        width: 100%;
+        margin: 0;
+    }
+
+    div.footer {
+        display: none;
+    }
+
+    div.bodywrapper {
+        margin: 0;
+    }
+
+    div.body {
+        min-height: 0;
+        padding: 0;
+    }
+
+    .rtd_doc_footer {
+        display: none;
+    }
+
+    .document {
+        width: auto;
+    }
+
+    .footer {
+        width: auto;
+    }
+
+    .footer {
+        width: auto;
+    }
+
+    .github {
+        display: none;
+    }
+}
+
+
+/* misc. */
+
+.revsys-inline {
+    display: none!important;
+}
+
+/* Make nested-list/multi-paragraph items look better in Releases changelog
+ * pages. Without this, docutils' magical list fuckery causes inconsistent
+ * formatting between different release sub-lists.
+ */
+div#changelog > div.section > ul > li > p:only-child {
+    margin-bottom: 0;
+}
+
+/* Hide fugly table cell borders in ..bibliography:: directive output */
+table.docutils.citation, table.docutils.citation td, table.docutils.citation th {
+  border: none;
+  /* Below needed in some edge cases; if not applied, bottom shadows appear */
+  -moz-box-shadow: none;
+  -webkit-box-shadow: none;
+  box-shadow: none;
+}

+ 604 - 0
doc/_build/html/_static/basic.css

@@ -0,0 +1,604 @@
+/*
+ * basic.css
+ * ~~~~~~~~~
+ *
+ * Sphinx stylesheet -- basic theme.
+ *
+ * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/* -- main layout ----------------------------------------------------------- */
+
+div.clearer {
+    clear: both;
+}
+
+/* -- relbar ---------------------------------------------------------------- */
+
+div.related {
+    width: 100%;
+    font-size: 90%;
+}
+
+div.related h3 {
+    display: none;
+}
+
+div.related ul {
+    margin: 0;
+    padding: 0 0 0 10px;
+    list-style: none;
+}
+
+div.related li {
+    display: inline;
+}
+
+div.related li.right {
+    float: right;
+    margin-right: 5px;
+}
+
+/* -- sidebar --------------------------------------------------------------- */
+
+div.sphinxsidebarwrapper {
+    padding: 10px 5px 0 10px;
+}
+
+div.sphinxsidebar {
+    float: left;
+    width: 230px;
+    margin-left: -100%;
+    font-size: 90%;
+    word-wrap: break-word;
+    overflow-wrap : break-word;
+}
+
+div.sphinxsidebar ul {
+    list-style: none;
+}
+
+div.sphinxsidebar ul ul,
+div.sphinxsidebar ul.want-points {
+    margin-left: 20px;
+    list-style: square;
+}
+
+div.sphinxsidebar ul ul {
+    margin-top: 0;
+    margin-bottom: 0;
+}
+
+div.sphinxsidebar form {
+    margin-top: 10px;
+}
+
+div.sphinxsidebar input {
+    border: 1px solid #98dbcc;
+    font-family: sans-serif;
+    font-size: 1em;
+}
+
+div.sphinxsidebar #searchbox input[type="text"] {
+    width: 170px;
+}
+
+img {
+    border: 0;
+    max-width: 100%;
+}
+
+/* -- search page ----------------------------------------------------------- */
+
+ul.search {
+    margin: 10px 0 0 20px;
+    padding: 0;
+}
+
+ul.search li {
+    padding: 5px 0 5px 20px;
+    background-image: url(file.png);
+    background-repeat: no-repeat;
+    background-position: 0 7px;
+}
+
+ul.search li a {
+    font-weight: bold;
+}
+
+ul.search li div.context {
+    color: #888;
+    margin: 2px 0 0 30px;
+    text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+    font-weight: bold;
+}
+
+/* -- index page ------------------------------------------------------------ */
+
+table.contentstable {
+    width: 90%;
+}
+
+table.contentstable p.biglink {
+    line-height: 150%;
+}
+
+a.biglink {
+    font-size: 1.3em;
+}
+
+span.linkdescr {
+    font-style: italic;
+    padding-top: 5px;
+    font-size: 90%;
+}
+
+/* -- general index --------------------------------------------------------- */
+
+table.indextable {
+    width: 100%;
+}
+
+table.indextable td {
+    text-align: left;
+    vertical-align: top;
+}
+
+table.indextable dl, table.indextable dd {
+    margin-top: 0;
+    margin-bottom: 0;
+}
+
+table.indextable tr.pcap {
+    height: 10px;
+}
+
+table.indextable tr.cap {
+    margin-top: 10px;
+    background-color: #f2f2f2;
+}
+
+img.toggler {
+    margin-right: 3px;
+    margin-top: 3px;
+    cursor: pointer;
+}
+
+div.modindex-jumpbox {
+    border-top: 1px solid #ddd;
+    border-bottom: 1px solid #ddd;
+    margin: 1em 0 1em 0;
+    padding: 0.4em;
+}
+
+div.genindex-jumpbox {
+    border-top: 1px solid #ddd;
+    border-bottom: 1px solid #ddd;
+    margin: 1em 0 1em 0;
+    padding: 0.4em;
+}
+
+/* -- general body styles --------------------------------------------------- */
+
+div.body p, div.body dd, div.body li, div.body blockquote {
+    -moz-hyphens: auto;
+    -ms-hyphens: auto;
+    -webkit-hyphens: auto;
+    hyphens: auto;
+}
+
+a.headerlink {
+    visibility: hidden;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink,
+caption:hover > a.headerlink,
+p.caption:hover > a.headerlink,
+div.code-block-caption:hover > a.headerlink {
+    visibility: visible;
+}
+
+div.body p.caption {
+    text-align: inherit;
+}
+
+div.body td {
+    text-align: left;
+}
+
+.field-list ul {
+    padding-left: 1em;
+}
+
+.first {
+    margin-top: 0 !important;
+}
+
+p.rubric {
+    margin-top: 30px;
+    font-weight: bold;
+}
+
+img.align-left, .figure.align-left, object.align-left {
+    clear: left;
+    float: left;
+    margin-right: 1em;
+}
+
+img.align-right, .figure.align-right, object.align-right {
+    clear: right;
+    float: right;
+    margin-left: 1em;
+}
+
+img.align-center, .figure.align-center, object.align-center {
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.align-left {
+    text-align: left;
+}
+
+.align-center {
+    text-align: center;
+}
+
+.align-right {
+    text-align: right;
+}
+
+/* -- sidebars -------------------------------------------------------------- */
+
+div.sidebar {
+    margin: 0 0 0.5em 1em;
+    border: 1px solid #ddb;
+    padding: 7px 7px 0 7px;
+    background-color: #ffe;
+    width: 40%;
+    float: right;
+}
+
+p.sidebar-title {
+    font-weight: bold;
+}
+
+/* -- topics ---------------------------------------------------------------- */
+
+div.topic {
+    border: 1px solid #ccc;
+    padding: 7px 7px 0 7px;
+    margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+    font-size: 1.1em;
+    font-weight: bold;
+    margin-top: 10px;
+}
+
+/* -- admonitions ----------------------------------------------------------- */
+
+div.admonition {
+    margin-top: 10px;
+    margin-bottom: 10px;
+    padding: 7px;
+}
+
+div.admonition dt {
+    font-weight: bold;
+}
+
+div.admonition dl {
+    margin-bottom: 0;
+}
+
+p.admonition-title {
+    margin: 0px 10px 5px 0px;
+    font-weight: bold;
+}
+
+div.body p.centered {
+    text-align: center;
+    margin-top: 25px;
+}
+
+/* -- tables ---------------------------------------------------------------- */
+
+table.docutils {
+    border: 0;
+    border-collapse: collapse;
+}
+
+table caption span.caption-number {
+    font-style: italic;
+}
+
+table caption span.caption-text {
+}
+
+table.docutils td, table.docutils th {
+    padding: 1px 8px 1px 5px;
+    border-top: 0;
+    border-left: 0;
+    border-right: 0;
+    border-bottom: 1px solid #aaa;
+}
+
+table.field-list td, table.field-list th {
+    border: 0 !important;
+}
+
+table.footnote td, table.footnote th {
+    border: 0 !important;
+}
+
+th {
+    text-align: left;
+    padding-right: 5px;
+}
+
+table.citation {
+    border-left: solid 1px gray;
+    margin-left: 1px;
+}
+
+table.citation td {
+    border-bottom: none;
+}
+
+/* -- figures --------------------------------------------------------------- */
+
+div.figure {
+    margin: 0.5em;
+    padding: 0.5em;
+}
+
+div.figure p.caption {
+    padding: 0.3em;
+}
+
+div.figure p.caption span.caption-number {
+    font-style: italic;
+}
+
+div.figure p.caption span.caption-text {
+}
+
+
+/* -- other body styles ----------------------------------------------------- */
+
+ol.arabic {
+    list-style: decimal;
+}
+
+ol.loweralpha {
+    list-style: lower-alpha;
+}
+
+ol.upperalpha {
+    list-style: upper-alpha;
+}
+
+ol.lowerroman {
+    list-style: lower-roman;
+}
+
+ol.upperroman {
+    list-style: upper-roman;
+}
+
+dl {
+    margin-bottom: 15px;
+}
+
+dd p {
+    margin-top: 0px;
+}
+
+dd ul, dd table {
+    margin-bottom: 10px;
+}
+
+dd {
+    margin-top: 3px;
+    margin-bottom: 10px;
+    margin-left: 30px;
+}
+
+dt:target, .highlighted {
+    background-color: #fbe54e;
+}
+
+dl.glossary dt {
+    font-weight: bold;
+    font-size: 1.1em;
+}
+
+.field-list ul {
+    margin: 0;
+    padding-left: 1em;
+}
+
+.field-list p {
+    margin: 0;
+}
+
+.optional {
+    font-size: 1.3em;
+}
+
+.sig-paren {
+    font-size: larger;
+}
+
+.versionmodified {
+    font-style: italic;
+}
+
+.system-message {
+    background-color: #fda;
+    padding: 5px;
+    border: 3px solid red;
+}
+
+.footnote:target  {
+    background-color: #ffa;
+}
+
+.line-block {
+    display: block;
+    margin-top: 1em;
+    margin-bottom: 1em;
+}
+
+.line-block .line-block {
+    margin-top: 0;
+    margin-bottom: 0;
+    margin-left: 1.5em;
+}
+
+.guilabel, .menuselection {
+    font-family: sans-serif;
+}
+
+.accelerator {
+    text-decoration: underline;
+}
+
+.classifier {
+    font-style: oblique;
+}
+
+abbr, acronym {
+    border-bottom: dotted 1px;
+    cursor: help;
+}
+
+/* -- code displays --------------------------------------------------------- */
+
+pre {
+    overflow: auto;
+    overflow-y: hidden;  /* fixes display issues on Chrome browsers */
+}
+
+td.linenos pre {
+    padding: 5px 0px;
+    border: 0;
+    background-color: transparent;
+    color: #aaa;
+}
+
+table.highlighttable {
+    margin-left: 0.5em;
+}
+
+table.highlighttable td {
+    padding: 0 0.5em 0 0.5em;
+}
+
+div.code-block-caption {
+    padding: 2px 5px;
+    font-size: small;
+}
+
+div.code-block-caption code {
+    background-color: transparent;
+}
+
+div.code-block-caption + div > div.highlight > pre {
+    margin-top: 0;
+}
+
+div.code-block-caption span.caption-number {
+    padding: 0.1em 0.3em;
+    font-style: italic;
+}
+
+div.code-block-caption span.caption-text {
+}
+
+div.literal-block-wrapper {
+    padding: 1em 1em 0;
+}
+
+div.literal-block-wrapper div.highlight {
+    margin: 0;
+}
+
+code.descname {
+    background-color: transparent;
+    font-weight: bold;
+    font-size: 1.2em;
+}
+
+code.descclassname {
+    background-color: transparent;
+}
+
+code.xref, a code {
+    background-color: transparent;
+    font-weight: bold;
+}
+
+h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
+    background-color: transparent;
+}
+
+.viewcode-link {
+    float: right;
+}
+
+.viewcode-back {
+    float: right;
+    font-family: sans-serif;
+}
+
+div.viewcode-block:target {
+    margin: -1px -10px;
+    padding: 0 10px;
+}
+
+/* -- math display ---------------------------------------------------------- */
+
+img.math {
+    vertical-align: middle;
+}
+
+div.body div.math p {
+    text-align: center;
+}
+
+span.eqno {
+    float: right;
+}
+
+/* -- printout stylesheet --------------------------------------------------- */
+
+@media print {
+    div.document,
+    div.documentwrapper,
+    div.bodywrapper {
+        margin: 0 !important;
+        width: 100%;
+    }
+
+    div.sphinxsidebar,
+    div.related,
+    div.footer,
+    #top-link {
+        display: none;
+    }
+}

+ 261 - 0
doc/_build/html/_static/classic.css

@@ -0,0 +1,261 @@
+/*
+ * default.css_t
+ * ~~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- default theme.
+ *
+ * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+@import url("basic.css");
+
+/* -- page layout ----------------------------------------------------------- */
+
+body {
+    font-family: sans-serif;
+    font-size: 100%;
+    background-color: #11303d;
+    color: #000;
+    margin: 0;
+    padding: 0;
+}
+
+div.document {
+    background-color: #1c4e63;
+}
+
+div.documentwrapper {
+    float: left;
+    width: 100%;
+}
+
+div.bodywrapper {
+    margin: 0 0 0 230px;
+}
+
+div.body {
+    background-color: #ffffff;
+    color: #000000;
+    padding: 0 20px 30px 20px;
+}
+
+div.footer {
+    color: #ffffff;
+    width: 100%;
+    padding: 9px 0 9px 0;
+    text-align: center;
+    font-size: 75%;
+}
+
+div.footer a {
+    color: #ffffff;
+    text-decoration: underline;
+}
+
+div.related {
+    background-color: #133f52;
+    line-height: 30px;
+    color: #ffffff;
+}
+
+div.related a {
+    color: #ffffff;
+}
+
+div.sphinxsidebar {
+}
+
+div.sphinxsidebar h3 {
+    font-family: 'Trebuchet MS', sans-serif;
+    color: #ffffff;
+    font-size: 1.4em;
+    font-weight: normal;
+    margin: 0;
+    padding: 0;
+}
+
+div.sphinxsidebar h3 a {
+    color: #ffffff;
+}
+
+div.sphinxsidebar h4 {
+    font-family: 'Trebuchet MS', sans-serif;
+    color: #ffffff;
+    font-size: 1.3em;
+    font-weight: normal;
+    margin: 5px 0 0 0;
+    padding: 0;
+}
+
+div.sphinxsidebar p {
+    color: #ffffff;
+}
+
+div.sphinxsidebar p.topless {
+    margin: 5px 10px 10px 10px;
+}
+
+div.sphinxsidebar ul {
+    margin: 10px;
+    padding: 0;
+    color: #ffffff;
+}
+
+div.sphinxsidebar a {
+    color: #98dbcc;
+}
+
+div.sphinxsidebar input {
+    border: 1px solid #98dbcc;
+    font-family: sans-serif;
+    font-size: 1em;
+}
+
+
+
+/* -- hyperlink styles ------------------------------------------------------ */
+
+a {
+    color: #355f7c;
+    text-decoration: none;
+}
+
+a:visited {
+    color: #355f7c;
+    text-decoration: none;
+}
+
+a:hover {
+    text-decoration: underline;
+}
+
+
+
+/* -- body styles ----------------------------------------------------------- */
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+    font-family: 'Trebuchet MS', sans-serif;
+    background-color: #f2f2f2;
+    font-weight: normal;
+    color: #20435c;
+    border-bottom: 1px solid #ccc;
+    margin: 20px -20px 10px -20px;
+    padding: 3px 0 3px 10px;
+}
+
+div.body h1 { margin-top: 0; font-size: 200%; }
+div.body h2 { font-size: 160%; }
+div.body h3 { font-size: 140%; }
+div.body h4 { font-size: 120%; }
+div.body h5 { font-size: 110%; }
+div.body h6 { font-size: 100%; }
+
+a.headerlink {
+    color: #c60f0f;
+    font-size: 0.8em;
+    padding: 0 4px 0 4px;
+    text-decoration: none;
+}
+
+a.headerlink:hover {
+    background-color: #c60f0f;
+    color: white;
+}
+
+div.body p, div.body dd, div.body li, div.body blockquote {
+    text-align: justify;
+    line-height: 130%;
+}
+
+div.admonition p.admonition-title + p {
+    display: inline;
+}
+
+div.admonition p {
+    margin-bottom: 5px;
+}
+
+div.admonition pre {
+    margin-bottom: 5px;
+}
+
+div.admonition ul, div.admonition ol {
+    margin-bottom: 5px;
+}
+
+div.note {
+    background-color: #eee;
+    border: 1px solid #ccc;
+}
+
+div.seealso {
+    background-color: #ffc;
+    border: 1px solid #ff6;
+}
+
+div.topic {
+    background-color: #eee;
+}
+
+div.warning {
+    background-color: #ffe4e4;
+    border: 1px solid #f66;
+}
+
+p.admonition-title {
+    display: inline;
+}
+
+p.admonition-title:after {
+    content: ":";
+}
+
+pre {
+    padding: 5px;
+    background-color: #eeffcc;
+    color: #333333;
+    line-height: 120%;
+    border: 1px solid #ac9;
+    border-left: none;
+    border-right: none;
+}
+
+code {
+    background-color: #ecf0f3;
+    padding: 0 1px 0 1px;
+    font-size: 0.95em;
+}
+
+th {
+    background-color: #ede;
+}
+
+.warning code {
+    background: #efc2c2;
+}
+
+.note code {
+    background: #d6d6d6;
+}
+
+.viewcode-back {
+    font-family: sans-serif;
+}
+
+div.viewcode-block:target {
+    background-color: #f4debf;
+    border-top: 1px solid #ac9;
+    border-bottom: 1px solid #ac9;
+}
+
+div.code-block-caption {
+    color: #efefef;
+    background-color: #1c4e63;
+}

BIN
doc/_build/html/_static/comment-bright.png


BIN
doc/_build/html/_static/comment-close.png


BIN
doc/_build/html/_static/comment.png


+ 1 - 0
doc/_build/html/_static/custom.css

@@ -0,0 +1 @@
+/* This file intentionally left blank. */

+ 287 - 0
doc/_build/html/_static/doctools.js

@@ -0,0 +1,287 @@
+/*
+ * doctools.js
+ * ~~~~~~~~~~~
+ *
+ * Sphinx JavaScript utilities for all documentation.
+ *
+ * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+/**
+ * select a different prefix for underscore
+ */
+$u = _.noConflict();
+
+/**
+ * make the code below compatible with browsers without
+ * an installed firebug like debugger
+if (!window.console || !console.firebug) {
+  var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
+    "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
+    "profile", "profileEnd"];
+  window.console = {};
+  for (var i = 0; i < names.length; ++i)
+    window.console[names[i]] = function() {};
+}
+ */
+
+/**
+ * small helper function to urldecode strings
+ */
+jQuery.urldecode = function(x) {
+  return decodeURIComponent(x).replace(/\+/g, ' ');
+};
+
+/**
+ * small helper function to urlencode strings
+ */
+jQuery.urlencode = encodeURIComponent;
+
+/**
+ * This function returns the parsed url parameters of the
+ * current request. Multiple values per key are supported,
+ * it will always return arrays of strings for the value parts.
+ */
+jQuery.getQueryParameters = function(s) {
+  if (typeof s == 'undefined')
+    s = document.location.search;
+  var parts = s.substr(s.indexOf('?') + 1).split('&');
+  var result = {};
+  for (var i = 0; i < parts.length; i++) {
+    var tmp = parts[i].split('=', 2);
+    var key = jQuery.urldecode(tmp[0]);
+    var value = jQuery.urldecode(tmp[1]);
+    if (key in result)
+      result[key].push(value);
+    else
+      result[key] = [value];
+  }
+  return result;
+};
+
+/**
+ * highlight a given string on a jquery object by wrapping it in
+ * span elements with the given class name.
+ */
+jQuery.fn.highlightText = function(text, className) {
+  function highlight(node) {
+    if (node.nodeType == 3) {
+      var val = node.nodeValue;
+      var pos = val.toLowerCase().indexOf(text);
+      if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
+        var span = document.createElement("span");
+        span.className = className;
+        span.appendChild(document.createTextNode(val.substr(pos, text.length)));
+        node.parentNode.insertBefore(span, node.parentNode.insertBefore(
+          document.createTextNode(val.substr(pos + text.length)),
+          node.nextSibling));
+        node.nodeValue = val.substr(0, pos);
+      }
+    }
+    else if (!jQuery(node).is("button, select, textarea")) {
+      jQuery.each(node.childNodes, function() {
+        highlight(this);
+      });
+    }
+  }
+  return this.each(function() {
+    highlight(this);
+  });
+};
+
+/*
+ * backward compatibility for jQuery.browser
+ * This will be supported until firefox bug is fixed.
+ */
+if (!jQuery.browser) {
+  jQuery.uaMatch = function(ua) {
+    ua = ua.toLowerCase();
+
+    var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
+      /(webkit)[ \/]([\w.]+)/.exec(ua) ||
+      /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
+      /(msie) ([\w.]+)/.exec(ua) ||
+      ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
+      [];
+
+    return {
+      browser: match[ 1 ] || "",
+      version: match[ 2 ] || "0"
+    };
+  };
+  jQuery.browser = {};
+  jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
+}
+
+/**
+ * Small JavaScript module for the documentation.
+ */
+var Documentation = {
+
+  init : function() {
+    this.fixFirefoxAnchorBug();
+    this.highlightSearchWords();
+    this.initIndexTable();
+    
+  },
+
+  /**
+   * i18n support
+   */
+  TRANSLATIONS : {},
+  PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; },
+  LOCALE : 'unknown',
+
+  // gettext and ngettext don't access this so that the functions
+  // can safely bound to a different name (_ = Documentation.gettext)
+  gettext : function(string) {
+    var translated = Documentation.TRANSLATIONS[string];
+    if (typeof translated == 'undefined')
+      return string;
+    return (typeof translated == 'string') ? translated : translated[0];
+  },
+
+  ngettext : function(singular, plural, n) {
+    var translated = Documentation.TRANSLATIONS[singular];
+    if (typeof translated == 'undefined')
+      return (n == 1) ? singular : plural;
+    return translated[Documentation.PLURALEXPR(n)];
+  },
+
+  addTranslations : function(catalog) {
+    for (var key in catalog.messages)
+      this.TRANSLATIONS[key] = catalog.messages[key];
+    this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
+    this.LOCALE = catalog.locale;
+  },
+
+  /**
+   * add context elements like header anchor links
+   */
+  addContextElements : function() {
+    $('div[id] > :header:first').each(function() {
+      $('<a class="headerlink">\u00B6</a>').
+      attr('href', '#' + this.id).
+      attr('title', _('Permalink to this headline')).
+      appendTo(this);
+    });
+    $('dt[id]').each(function() {
+      $('<a class="headerlink">\u00B6</a>').
+      attr('href', '#' + this.id).
+      attr('title', _('Permalink to this definition')).
+      appendTo(this);
+    });
+  },
+
+  /**
+   * workaround a firefox stupidity
+   * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
+   */
+  fixFirefoxAnchorBug : function() {
+    if (document.location.hash)
+      window.setTimeout(function() {
+        document.location.href += '';
+      }, 10);
+  },
+
+  /**
+   * highlight the search words provided in the url in the text
+   */
+  highlightSearchWords : function() {
+    var params = $.getQueryParameters();
+    var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
+    if (terms.length) {
+      var body = $('div.body');
+      if (!body.length) {
+        body = $('body');
+      }
+      window.setTimeout(function() {
+        $.each(terms, function() {
+          body.highlightText(this.toLowerCase(), 'highlighted');
+        });
+      }, 10);
+      $('<p class="highlight-link"><a href="javascript:Documentation.' +
+        'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
+          .appendTo($('#searchbox'));
+    }
+  },
+
+  /**
+   * init the domain index toggle buttons
+   */
+  initIndexTable : function() {
+    var togglers = $('img.toggler').click(function() {
+      var src = $(this).attr('src');
+      var idnum = $(this).attr('id').substr(7);
+      $('tr.cg-' + idnum).toggle();
+      if (src.substr(-9) == 'minus.png')
+        $(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
+      else
+        $(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
+    }).css('display', '');
+    if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
+        togglers.click();
+    }
+  },
+
+  /**
+   * helper function to hide the search marks again
+   */
+  hideSearchWords : function() {
+    $('#searchbox .highlight-link').fadeOut(300);
+    $('span.highlighted').removeClass('highlighted');
+  },
+
+  /**
+   * make the url absolute
+   */
+  makeURL : function(relativeURL) {
+    return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
+  },
+
+  /**
+   * get the current relative url
+   */
+  getCurrentURL : function() {
+    var path = document.location.pathname;
+    var parts = path.split(/\//);
+    $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
+      if (this == '..')
+        parts.pop();
+    });
+    var url = parts.join('/');
+    return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
+  },
+
+  initOnKeyListeners: function() {
+    $(document).keyup(function(event) {
+      var activeElementType = document.activeElement.tagName;
+      // don't navigate when in search box or textarea
+      if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') {
+        switch (event.keyCode) {
+          case 37: // left
+            var prevHref = $('link[rel="prev"]').prop('href');
+            if (prevHref) {
+              window.location.href = prevHref;
+              return false;
+            }
+          case 39: // right
+            var nextHref = $('link[rel="next"]').prop('href');
+            if (nextHref) {
+              window.location.href = nextHref;
+              return false;
+            }
+        }
+      }
+    });
+  }
+};
+
+// quick alias for translations
+_ = Documentation.gettext;
+
+$(document).ready(function() {
+  Documentation.init();
+});

BIN
doc/_build/html/_static/down-pressed.png


BIN
doc/_build/html/_static/down.png


BIN
doc/_build/html/_static/file.png


Разница между файлами не показана из-за своего большого размера
+ 10308 - 0
doc/_build/html/_static/jquery-1.11.1.js


Разница между файлами не показана из-за своего большого размера
+ 4 - 0
doc/_build/html/_static/jquery.js


BIN
doc/_build/html/_static/minus.png


BIN
doc/_build/html/_static/plus.png


+ 63 - 0
doc/_build/html/_static/pygments.css

@@ -0,0 +1,63 @@
+.highlight .hll { background-color: #ffffcc }
+.highlight  { background: #eeffcc; }
+.highlight .c { color: #408090; font-style: italic } /* Comment */
+.highlight .err { border: 1px solid #FF0000 } /* Error */
+.highlight .k { color: #007020; font-weight: bold } /* Keyword */
+.highlight .o { color: #666666 } /* Operator */
+.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
+.highlight .cp { color: #007020 } /* Comment.Preproc */
+.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
+.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
+.highlight .gd { color: #A00000 } /* Generic.Deleted */
+.highlight .ge { font-style: italic } /* Generic.Emph */
+.highlight .gr { color: #FF0000 } /* Generic.Error */
+.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
+.highlight .gi { color: #00A000 } /* Generic.Inserted */
+.highlight .go { color: #333333 } /* Generic.Output */
+.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
+.highlight .gs { font-weight: bold } /* Generic.Strong */
+.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
+.highlight .gt { color: #0044DD } /* Generic.Traceback */
+.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
+.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
+.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
+.highlight .kp { color: #007020 } /* Keyword.Pseudo */
+.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
+.highlight .kt { color: #902000 } /* Keyword.Type */
+.highlight .m { color: #208050 } /* Literal.Number */
+.highlight .s { color: #4070a0 } /* Literal.String */
+.highlight .na { color: #4070a0 } /* Name.Attribute */
+.highlight .nb { color: #007020 } /* Name.Builtin */
+.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
+.highlight .no { color: #60add5 } /* Name.Constant */
+.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
+.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
+.highlight .ne { color: #007020 } /* Name.Exception */
+.highlight .nf { color: #06287e } /* Name.Function */
+.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
+.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
+.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
+.highlight .nv { color: #bb60d5 } /* Name.Variable */
+.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
+.highlight .w { color: #bbbbbb } /* Text.Whitespace */
+.highlight .mb { color: #208050 } /* Literal.Number.Bin */
+.highlight .mf { color: #208050 } /* Literal.Number.Float */
+.highlight .mh { color: #208050 } /* Literal.Number.Hex */
+.highlight .mi { color: #208050 } /* Literal.Number.Integer */
+.highlight .mo { color: #208050 } /* Literal.Number.Oct */
+.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
+.highlight .sc { color: #4070a0 } /* Literal.String.Char */
+.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
+.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
+.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
+.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
+.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
+.highlight .sx { color: #c65d09 } /* Literal.String.Other */
+.highlight .sr { color: #235388 } /* Literal.String.Regex */
+.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
+.highlight .ss { color: #517918 } /* Literal.String.Symbol */
+.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
+.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
+.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
+.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
+.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */

+ 651 - 0
doc/_build/html/_static/searchtools.js

@@ -0,0 +1,651 @@
+/*
+ * searchtools.js_t
+ * ~~~~~~~~~~~~~~~~
+ *
+ * Sphinx JavaScript utilities for the full-text search.
+ *
+ * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+
+/* Non-minified version JS is _stemmer.js if file is provided */ 
+/**
+ * Porter Stemmer
+ */
+var Stemmer = function() {
+
+  var step2list = {
+    ational: 'ate',
+    tional: 'tion',
+    enci: 'ence',
+    anci: 'ance',
+    izer: 'ize',
+    bli: 'ble',
+    alli: 'al',
+    entli: 'ent',
+    eli: 'e',
+    ousli: 'ous',
+    ization: 'ize',
+    ation: 'ate',
+    ator: 'ate',
+    alism: 'al',
+    iveness: 'ive',
+    fulness: 'ful',
+    ousness: 'ous',
+    aliti: 'al',
+    iviti: 'ive',
+    biliti: 'ble',
+    logi: 'log'
+  };
+
+  var step3list = {
+    icate: 'ic',
+    ative: '',
+    alize: 'al',
+    iciti: 'ic',
+    ical: 'ic',
+    ful: '',
+    ness: ''
+  };
+
+  var c = "[^aeiou]";          // consonant
+  var v = "[aeiouy]";          // vowel
+  var C = c + "[^aeiouy]*";    // consonant sequence
+  var V = v + "[aeiou]*";      // vowel sequence
+
+  var mgr0 = "^(" + C + ")?" + V + C;                      // [C]VC... is m>0
+  var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$";    // [C]VC[V] is m=1
+  var mgr1 = "^(" + C + ")?" + V + C + V + C;              // [C]VCVC... is m>1
+  var s_v   = "^(" + C + ")?" + v;                         // vowel in stem
+
+  this.stemWord = function (w) {
+    var stem;
+    var suffix;
+    var firstch;
+    var origword = w;
+
+    if (w.length < 3)
+      return w;
+
+    var re;
+    var re2;
+    var re3;
+    var re4;
+
+    firstch = w.substr(0,1);
+    if (firstch == "y")
+      w = firstch.toUpperCase() + w.substr(1);
+
+    // Step 1a
+    re = /^(.+?)(ss|i)es$/;
+    re2 = /^(.+?)([^s])s$/;
+
+    if (re.test(w))
+      w = w.replace(re,"$1$2");
+    else if (re2.test(w))
+      w = w.replace(re2,"$1$2");
+
+    // Step 1b
+    re = /^(.+?)eed$/;
+    re2 = /^(.+?)(ed|ing)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      re = new RegExp(mgr0);
+      if (re.test(fp[1])) {
+        re = /.$/;
+        w = w.replace(re,"");
+      }
+    }
+    else if (re2.test(w)) {
+      var fp = re2.exec(w);
+      stem = fp[1];
+      re2 = new RegExp(s_v);
+      if (re2.test(stem)) {
+        w = stem;
+        re2 = /(at|bl|iz)$/;
+        re3 = new RegExp("([^aeiouylsz])\\1$");
+        re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+        if (re2.test(w))
+          w = w + "e";
+        else if (re3.test(w)) {
+          re = /.$/;
+          w = w.replace(re,"");
+        }
+        else if (re4.test(w))
+          w = w + "e";
+      }
+    }
+
+    // Step 1c
+    re = /^(.+?)y$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      re = new RegExp(s_v);
+      if (re.test(stem))
+        w = stem + "i";
+    }
+
+    // Step 2
+    re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      suffix = fp[2];
+      re = new RegExp(mgr0);
+      if (re.test(stem))
+        w = stem + step2list[suffix];
+    }
+
+    // Step 3
+    re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      suffix = fp[2];
+      re = new RegExp(mgr0);
+      if (re.test(stem))
+        w = stem + step3list[suffix];
+    }
+
+    // Step 4
+    re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
+    re2 = /^(.+?)(s|t)(ion)$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      re = new RegExp(mgr1);
+      if (re.test(stem))
+        w = stem;
+    }
+    else if (re2.test(w)) {
+      var fp = re2.exec(w);
+      stem = fp[1] + fp[2];
+      re2 = new RegExp(mgr1);
+      if (re2.test(stem))
+        w = stem;
+    }
+
+    // Step 5
+    re = /^(.+?)e$/;
+    if (re.test(w)) {
+      var fp = re.exec(w);
+      stem = fp[1];
+      re = new RegExp(mgr1);
+      re2 = new RegExp(meq1);
+      re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
+      if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
+        w = stem;
+    }
+    re = /ll$/;
+    re2 = new RegExp(mgr1);
+    if (re.test(w) && re2.test(w)) {
+      re = /.$/;
+      w = w.replace(re,"");
+    }
+
+    // and turn initial Y back to y
+    if (firstch == "y")
+      w = firstch.toLowerCase() + w.substr(1);
+    return w;
+  }
+}
+
+
+
+/**
+ * Simple result scoring code.
+ */
+var Scorer = {
+  // Implement the following function to further tweak the score for each result
+  // The function takes a result array [filename, title, anchor, descr, score]
+  // and returns the new score.
+  /*
+  score: function(result) {
+    return result[4];
+  },
+  */
+
+  // query matches the full name of an object
+  objNameMatch: 11,
+  // or matches in the last dotted part of the object name
+  objPartialMatch: 6,
+  // Additive scores depending on the priority of the object
+  objPrio: {0:  15,   // used to be importantResults
+            1:  5,   // used to be objectResults
+            2: -5},  // used to be unimportantResults
+  //  Used when the priority is not in the mapping.
+  objPrioDefault: 0,
+
+  // query found in title
+  title: 15,
+  // query found in terms
+  term: 5
+};
+
+
+/**
+ * Search Module
+ */
+var Search = {
+
+  _index : null,
+  _queued_query : null,
+  _pulse_status : -1,
+
+  init : function() {
+      var params = $.getQueryParameters();
+      if (params.q) {
+          var query = params.q[0];
+          $('input[name="q"]')[0].value = query;
+          this.performSearch(query);
+      }
+  },
+
+  loadIndex : function(url) {
+    $.ajax({type: "GET", url: url, data: null,
+            dataType: "script", cache: true,
+            complete: function(jqxhr, textstatus) {
+              if (textstatus != "success") {
+                document.getElementById("searchindexloader").src = url;
+              }
+            }});
+  },
+
+  setIndex : function(index) {
+    var q;
+    this._index = index;
+    if ((q = this._queued_query) !== null) {
+      this._queued_query = null;
+      Search.query(q);
+    }
+  },
+
+  hasIndex : function() {
+      return this._index !== null;
+  },
+
+  deferQuery : function(query) {
+      this._queued_query = query;
+  },
+
+  stopPulse : function() {
+      this._pulse_status = 0;
+  },
+
+  startPulse : function() {
+    if (this._pulse_status >= 0)
+        return;
+    function pulse() {
+      var i;
+      Search._pulse_status = (Search._pulse_status + 1) % 4;
+      var dotString = '';
+      for (i = 0; i < Search._pulse_status; i++)
+        dotString += '.';
+      Search.dots.text(dotString);
+      if (Search._pulse_status > -1)
+        window.setTimeout(pulse, 500);
+    }
+    pulse();
+  },
+
+  /**
+   * perform a search for something (or wait until index is loaded)
+   */
+  performSearch : function(query) {
+    // create the required interface elements
+    this.out = $('#search-results');
+    this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
+    this.dots = $('<span></span>').appendTo(this.title);
+    this.status = $('<p style="display: none"></p>').appendTo(this.out);
+    this.output = $('<ul class="search"/>').appendTo(this.out);
+
+    $('#search-progress').text(_('Preparing search...'));
+    this.startPulse();
+
+    // index already loaded, the browser was quick!
+    if (this.hasIndex())
+      this.query(query);
+    else
+      this.deferQuery(query);
+  },
+
+  /**
+   * execute search (requires search index to be loaded)
+   */
+  query : function(query) {
+    var i;
+    var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
+
+    // stem the searchterms and add them to the correct list
+    var stemmer = new Stemmer();
+    var searchterms = [];
+    var excluded = [];
+    var hlterms = [];
+    var tmp = query.split(/\s+/);
+    var objectterms = [];
+    for (i = 0; i < tmp.length; i++) {
+      if (tmp[i] !== "") {
+          objectterms.push(tmp[i].toLowerCase());
+      }
+
+      if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) ||
+          tmp[i] === "") {
+        // skip this "word"
+        continue;
+      }
+      // stem the word
+      var word = stemmer.stemWord(tmp[i].toLowerCase());
+      var toAppend;
+      // select the correct list
+      if (word[0] == '-') {
+        toAppend = excluded;
+        word = word.substr(1);
+      }
+      else {
+        toAppend = searchterms;
+        hlterms.push(tmp[i].toLowerCase());
+      }
+      // only add if not already in the list
+      if (!$u.contains(toAppend, word))
+        toAppend.push(word);
+    }
+    var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
+
+    // console.debug('SEARCH: searching for:');
+    // console.info('required: ', searchterms);
+    // console.info('excluded: ', excluded);
+
+    // prepare search
+    var terms = this._index.terms;
+    var titleterms = this._index.titleterms;
+
+    // array of [filename, title, anchor, descr, score]
+    var results = [];
+    $('#search-progress').empty();
+
+    // lookup as object
+    for (i = 0; i < objectterms.length; i++) {
+      var others = [].concat(objectterms.slice(0, i),
+                             objectterms.slice(i+1, objectterms.length));
+      results = results.concat(this.performObjectSearch(objectterms[i], others));
+    }
+
+    // lookup as search terms in fulltext
+    results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
+
+    // let the scorer override scores with a custom scoring function
+    if (Scorer.score) {
+      for (i = 0; i < results.length; i++)
+        results[i][4] = Scorer.score(results[i]);
+    }
+
+    // now sort the results by score (in opposite order of appearance, since the
+    // display function below uses pop() to retrieve items) and then
+    // alphabetically
+    results.sort(function(a, b) {
+      var left = a[4];
+      var right = b[4];
+      if (left > right) {
+        return 1;
+      } else if (left < right) {
+        return -1;
+      } else {
+        // same score: sort alphabetically
+        left = a[1].toLowerCase();
+        right = b[1].toLowerCase();
+        return (left > right) ? -1 : ((left < right) ? 1 : 0);
+      }
+    });
+
+    // for debugging
+    //Search.lastresults = results.slice();  // a copy
+    //console.info('search results:', Search.lastresults);
+
+    // print the results
+    var resultCount = results.length;
+    function displayNextItem() {
+      // results left, load the summary and display it
+      if (results.length) {
+        var item = results.pop();
+        var listItem = $('<li style="display:none"></li>');
+        if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') {
+          // dirhtml builder
+          var dirname = item[0] + '/';
+          if (dirname.match(/\/index\/$/)) {
+            dirname = dirname.substring(0, dirname.length-6);
+          } else if (dirname == 'index/') {
+            dirname = '';
+          }
+          listItem.append($('<a/>').attr('href',
+            DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
+            highlightstring + item[2]).html(item[1]));
+        } else {
+          // normal html builders
+          listItem.append($('<a/>').attr('href',
+            item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
+            highlightstring + item[2]).html(item[1]));
+        }
+        if (item[3]) {
+          listItem.append($('<span> (' + item[3] + ')</span>'));
+          Search.output.append(listItem);
+          listItem.slideDown(5, function() {
+            displayNextItem();
+          });
+        } else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
+          $.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[0] + '.txt',
+                  dataType: "text",
+                  complete: function(jqxhr, textstatus) {
+                    var data = jqxhr.responseText;
+                    if (data !== '' && data !== undefined) {
+                      listItem.append(Search.makeSearchSummary(data, searchterms, hlterms));
+                    }
+                    Search.output.append(listItem);
+                    listItem.slideDown(5, function() {
+                      displayNextItem();
+                    });
+                  }});
+        } else {
+          // no source available, just display title
+          Search.output.append(listItem);
+          listItem.slideDown(5, function() {
+            displayNextItem();
+          });
+        }
+      }
+      // search finished, update title and status message
+      else {
+        Search.stopPulse();
+        Search.title.text(_('Search Results'));
+        if (!resultCount)
+          Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
+        else
+            Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
+        Search.status.fadeIn(500);
+      }
+    }
+    displayNextItem();
+  },
+
+  /**
+   * search for object names
+   */
+  performObjectSearch : function(object, otherterms) {
+    var filenames = this._index.filenames;
+    var objects = this._index.objects;
+    var objnames = this._index.objnames;
+    var titles = this._index.titles;
+
+    var i;
+    var results = [];
+
+    for (var prefix in objects) {
+      for (var name in objects[prefix]) {
+        var fullname = (prefix ? prefix + '.' : '') + name;
+        if (fullname.toLowerCase().indexOf(object) > -1) {
+          var score = 0;
+          var parts = fullname.split('.');
+          // check for different match types: exact matches of full name or
+          // "last name" (i.e. last dotted part)
+          if (fullname == object || parts[parts.length - 1] == object) {
+            score += Scorer.objNameMatch;
+          // matches in last name
+          } else if (parts[parts.length - 1].indexOf(object) > -1) {
+            score += Scorer.objPartialMatch;
+          }
+          var match = objects[prefix][name];
+          var objname = objnames[match[1]][2];
+          var title = titles[match[0]];
+          // If more than one term searched for, we require other words to be
+          // found in the name/title/description
+          if (otherterms.length > 0) {
+            var haystack = (prefix + ' ' + name + ' ' +
+                            objname + ' ' + title).toLowerCase();
+            var allfound = true;
+            for (i = 0; i < otherterms.length; i++) {
+              if (haystack.indexOf(otherterms[i]) == -1) {
+                allfound = false;
+                break;
+              }
+            }
+            if (!allfound) {
+              continue;
+            }
+          }
+          var descr = objname + _(', in ') + title;
+
+          var anchor = match[3];
+          if (anchor === '')
+            anchor = fullname;
+          else if (anchor == '-')
+            anchor = objnames[match[1]][1] + '-' + fullname;
+          // add custom score for some objects according to scorer
+          if (Scorer.objPrio.hasOwnProperty(match[2])) {
+            score += Scorer.objPrio[match[2]];
+          } else {
+            score += Scorer.objPrioDefault;
+          }
+          results.push([filenames[match[0]], fullname, '#'+anchor, descr, score]);
+        }
+      }
+    }
+
+    return results;
+  },
+
+  /**
+   * search for full-text terms in the index
+   */
+  performTermsSearch : function(searchterms, excluded, terms, titleterms) {
+    var filenames = this._index.filenames;
+    var titles = this._index.titles;
+
+    var i, j, file;
+    var fileMap = {};
+    var scoreMap = {};
+    var results = [];
+
+    // perform the search on the required terms
+    for (i = 0; i < searchterms.length; i++) {
+      var word = searchterms[i];
+      var files = [];
+      var _o = [
+        {files: terms[word], score: Scorer.term},
+        {files: titleterms[word], score: Scorer.title}
+      ];
+
+      // no match but word was a required one
+      if ($u.every(_o, function(o){return o.files === undefined;})) {
+        break;
+      }
+      // found search word in contents
+      $u.each(_o, function(o) {
+        var _files = o.files;
+        if (_files === undefined)
+          return
+
+        if (_files.length === undefined)
+          _files = [_files];
+        files = files.concat(_files);
+
+        // set score for the word in each file to Scorer.term
+        for (j = 0; j < _files.length; j++) {
+          file = _files[j];
+          if (!(file in scoreMap))
+            scoreMap[file] = {}
+          scoreMap[file][word] = o.score;
+        }
+      });
+
+      // create the mapping
+      for (j = 0; j < files.length; j++) {
+        file = files[j];
+        if (file in fileMap)
+          fileMap[file].push(word);
+        else
+          fileMap[file] = [word];
+      }
+    }
+
+    // now check if the files don't contain excluded terms
+    for (file in fileMap) {
+      var valid = true;
+
+      // check if all requirements are matched
+      if (fileMap[file].length != searchterms.length)
+          continue;
+
+      // ensure that none of the excluded terms is in the search result
+      for (i = 0; i < excluded.length; i++) {
+        if (terms[excluded[i]] == file ||
+            titleterms[excluded[i]] == file ||
+            $u.contains(terms[excluded[i]] || [], file) ||
+            $u.contains(titleterms[excluded[i]] || [], file)) {
+          valid = false;
+          break;
+        }
+      }
+
+      // if we have still a valid result we can add it to the result list
+      if (valid) {
+        // select one (max) score for the file.
+        // for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
+        var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
+        results.push([filenames[file], titles[file], '', null, score]);
+      }
+    }
+    return results;
+  },
+
+  /**
+   * helper function to return a node containing the
+   * search summary for a given text. keywords is a list
+   * of stemmed words, hlwords is the list of normal, unstemmed
+   * words. the first one is used to find the occurrence, the
+   * latter for highlighting it.
+   */
+  makeSearchSummary : function(text, keywords, hlwords) {
+    var textLower = text.toLowerCase();
+    var start = 0;
+    $.each(keywords, function() {
+      var i = textLower.indexOf(this.toLowerCase());
+      if (i > -1)
+        start = i;
+    });
+    start = Math.max(start - 120, 0);
+    var excerpt = ((start > 0) ? '...' : '') +
+      $.trim(text.substr(start, 240)) +
+      ((start + 240 - text.length) ? '...' : '');
+    var rv = $('<div class="context"></div>').text(excerpt);
+    $.each(hlwords, function() {
+      rv = rv.highlightText(this, 'highlighted');
+    });
+    return rv;
+  }
+};
+
+$(document).ready(function() {
+  Search.init();
+});

+ 159 - 0
doc/_build/html/_static/sidebar.js

@@ -0,0 +1,159 @@
+/*
+ * sidebar.js
+ * ~~~~~~~~~~
+ *
+ * This script makes the Sphinx sidebar collapsible.
+ *
+ * .sphinxsidebar contains .sphinxsidebarwrapper.  This script adds
+ * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton
+ * used to collapse and expand the sidebar.
+ *
+ * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden
+ * and the width of the sidebar and the margin-left of the document
+ * are decreased. When the sidebar is expanded the opposite happens.
+ * This script saves a per-browser/per-session cookie used to
+ * remember the position of the sidebar among the pages.
+ * Once the browser is closed the cookie is deleted and the position
+ * reset to the default (expanded).
+ *
+ * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+$(function() {
+  
+  
+  
+  
+  
+  
+  
+
+  // global elements used by the functions.
+  // the 'sidebarbutton' element is defined as global after its
+  // creation, in the add_sidebar_button function
+  var bodywrapper = $('.bodywrapper');
+  var sidebar = $('.sphinxsidebar');
+  var sidebarwrapper = $('.sphinxsidebarwrapper');
+
+  // for some reason, the document has no sidebar; do not run into errors
+  if (!sidebar.length) return;
+
+  // original margin-left of the bodywrapper and width of the sidebar
+  // with the sidebar expanded
+  var bw_margin_expanded = bodywrapper.css('margin-left');
+  var ssb_width_expanded = sidebar.width();
+
+  // margin-left of the bodywrapper and width of the sidebar
+  // with the sidebar collapsed
+  var bw_margin_collapsed = '.8em';
+  var ssb_width_collapsed = '.8em';
+
+  // colors used by the current theme
+  var dark_color = $('.related').css('background-color');
+  var light_color = $('.document').css('background-color');
+
+  function sidebar_is_collapsed() {
+    return sidebarwrapper.is(':not(:visible)');
+  }
+
+  function toggle_sidebar() {
+    if (sidebar_is_collapsed())
+      expand_sidebar();
+    else
+      collapse_sidebar();
+  }
+
+  function collapse_sidebar() {
+    sidebarwrapper.hide();
+    sidebar.css('width', ssb_width_collapsed);
+    bodywrapper.css('margin-left', bw_margin_collapsed);
+    sidebarbutton.css({
+        'margin-left': '0',
+        'height': bodywrapper.height()
+    });
+    sidebarbutton.find('span').text('»');
+    sidebarbutton.attr('title', _('Expand sidebar'));
+    document.cookie = 'sidebar=collapsed';
+  }
+
+  function expand_sidebar() {
+    bodywrapper.css('margin-left', bw_margin_expanded);
+    sidebar.css('width', ssb_width_expanded);
+    sidebarwrapper.show();
+    sidebarbutton.css({
+        'margin-left': ssb_width_expanded-12,
+        'height': bodywrapper.height()
+    });
+    sidebarbutton.find('span').text('«');
+    sidebarbutton.attr('title', _('Collapse sidebar'));
+    document.cookie = 'sidebar=expanded';
+  }
+
+  function add_sidebar_button() {
+    sidebarwrapper.css({
+        'float': 'left',
+        'margin-right': '0',
+        'width': ssb_width_expanded - 28
+    });
+    // create the button
+    sidebar.append(
+        '<div id="sidebarbutton"><span>&laquo;</span></div>'
+    );
+    var sidebarbutton = $('#sidebarbutton');
+    light_color = sidebarbutton.css('background-color');
+    // find the height of the viewport to center the '<<' in the page
+    var viewport_height;
+    if (window.innerHeight)
+ 	  viewport_height = window.innerHeight;
+    else
+	  viewport_height = $(window).height();
+    sidebarbutton.find('span').css({
+        'display': 'block',
+        'margin-top': (viewport_height - sidebar.position().top - 20) / 2
+    });
+
+    sidebarbutton.click(toggle_sidebar);
+    sidebarbutton.attr('title', _('Collapse sidebar'));
+    sidebarbutton.css({
+        'color': '#FFFFFF',
+        'border-left': '1px solid ' + dark_color,
+        'font-size': '1.2em',
+        'cursor': 'pointer',
+        'height': bodywrapper.height(),
+        'padding-top': '1px',
+        'margin-left': ssb_width_expanded - 12
+    });
+
+    sidebarbutton.hover(
+      function () {
+          $(this).css('background-color', dark_color);
+      },
+      function () {
+          $(this).css('background-color', light_color);
+      }
+    );
+  }
+
+  function set_position_from_cookie() {
+    if (!document.cookie)
+      return;
+    var items = document.cookie.split(';');
+    for(var k=0; k<items.length; k++) {
+      var key_val = items[k].split('=');
+      var key = key_val[0].replace(/ /, "");  // strip leading spaces
+      if (key == 'sidebar') {
+        var value = key_val[1];
+        if ((value == 'collapsed') && (!sidebar_is_collapsed()))
+          collapse_sidebar();
+        else if ((value == 'expanded') && (sidebar_is_collapsed()))
+          expand_sidebar();
+      }
+    }
+  }
+
+  add_sidebar_button();
+  var sidebarbutton = $('#sidebarbutton');
+  set_position_from_cookie();
+});

Разница между файлами не показана из-за своего большого размера
+ 999 - 0
doc/_build/html/_static/underscore-1.3.1.js


Разница между файлами не показана из-за своего большого размера
+ 31 - 0
doc/_build/html/_static/underscore.js


BIN
doc/_build/html/_static/up-pressed.png


BIN
doc/_build/html/_static/up.png


+ 808 - 0
doc/_build/html/_static/websupport.js

@@ -0,0 +1,808 @@
+/*
+ * websupport.js
+ * ~~~~~~~~~~~~~
+ *
+ * sphinx.websupport utilities for all documentation.
+ *
+ * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+
+(function($) {
+  $.fn.autogrow = function() {
+    return this.each(function() {
+    var textarea = this;
+
+    $.fn.autogrow.resize(textarea);
+
+    $(textarea)
+      .focus(function() {
+        textarea.interval = setInterval(function() {
+          $.fn.autogrow.resize(textarea);
+        }, 500);
+      })
+      .blur(function() {
+        clearInterval(textarea.interval);
+      });
+    });
+  };
+
+  $.fn.autogrow.resize = function(textarea) {
+    var lineHeight = parseInt($(textarea).css('line-height'), 10);
+    var lines = textarea.value.split('\n');
+    var columns = textarea.cols;
+    var lineCount = 0;
+    $.each(lines, function() {
+      lineCount += Math.ceil(this.length / columns) || 1;
+    });
+    var height = lineHeight * (lineCount + 1);
+    $(textarea).css('height', height);
+  };
+})(jQuery);
+
+(function($) {
+  var comp, by;
+
+  function init() {
+    initEvents();
+    initComparator();
+  }
+
+  function initEvents() {
+    $(document).on("click", 'a.comment-close', function(event) {
+      event.preventDefault();
+      hide($(this).attr('id').substring(2));
+    });
+    $(document).on("click", 'a.vote', function(event) {
+      event.preventDefault();
+      handleVote($(this));
+    });
+    $(document).on("click", 'a.reply', function(event) {
+      event.preventDefault();
+      openReply($(this).attr('id').substring(2));
+    });
+    $(document).on("click", 'a.close-reply', function(event) {
+      event.preventDefault();
+      closeReply($(this).attr('id').substring(2));
+    });
+    $(document).on("click", 'a.sort-option', function(event) {
+      event.preventDefault();
+      handleReSort($(this));
+    });
+    $(document).on("click", 'a.show-proposal', function(event) {
+      event.preventDefault();
+      showProposal($(this).attr('id').substring(2));
+    });
+    $(document).on("click", 'a.hide-proposal', function(event) {
+      event.preventDefault();
+      hideProposal($(this).attr('id').substring(2));
+    });
+    $(document).on("click", 'a.show-propose-change', function(event) {
+      event.preventDefault();
+      showProposeChange($(this).attr('id').substring(2));
+    });
+    $(document).on("click", 'a.hide-propose-change', function(event) {
+      event.preventDefault();
+      hideProposeChange($(this).attr('id').substring(2));
+    });
+    $(document).on("click", 'a.accept-comment', function(event) {
+      event.preventDefault();
+      acceptComment($(this).attr('id').substring(2));
+    });
+    $(document).on("click", 'a.delete-comment', function(event) {
+      event.preventDefault();
+      deleteComment($(this).attr('id').substring(2));
+    });
+    $(document).on("click", 'a.comment-markup', function(event) {
+      event.preventDefault();
+      toggleCommentMarkupBox($(this).attr('id').substring(2));
+    });
+  }
+
+  /**
+   * Set comp, which is a comparator function used for sorting and
+   * inserting comments into the list.
+   */
+  function setComparator() {
+    // If the first three letters are "asc", sort in ascending order
+    // and remove the prefix.
+    if (by.substring(0,3) == 'asc') {
+      var i = by.substring(3);
+      comp = function(a, b) { return a[i] - b[i]; };
+    } else {
+      // Otherwise sort in descending order.
+      comp = function(a, b) { return b[by] - a[by]; };
+    }
+
+    // Reset link styles and format the selected sort option.
+    $('a.sel').attr('href', '#').removeClass('sel');
+    $('a.by' + by).removeAttr('href').addClass('sel');
+  }
+
+  /**
+   * Create a comp function. If the user has preferences stored in
+   * the sortBy cookie, use those, otherwise use the default.
+   */
+  function initComparator() {
+    by = 'rating'; // Default to sort by rating.
+    // If the sortBy cookie is set, use that instead.
+    if (document.cookie.length > 0) {
+      var start = document.cookie.indexOf('sortBy=');
+      if (start != -1) {
+        start = start + 7;
+        var end = document.cookie.indexOf(";", start);
+        if (end == -1) {
+          end = document.cookie.length;
+          by = unescape(document.cookie.substring(start, end));
+        }
+      }
+    }
+    setComparator();
+  }
+
+  /**
+   * Show a comment div.
+   */
+  function show(id) {
+    $('#ao' + id).hide();
+    $('#ah' + id).show();
+    var context = $.extend({id: id}, opts);
+    var popup = $(renderTemplate(popupTemplate, context)).hide();
+    popup.find('textarea[name="proposal"]').hide();
+    popup.find('a.by' + by).addClass('sel');
+    var form = popup.find('#cf' + id);
+    form.submit(function(event) {
+      event.preventDefault();
+      addComment(form);
+    });
+    $('#s' + id).after(popup);
+    popup.slideDown('fast', function() {
+      getComments(id);
+    });
+  }
+
+  /**
+   * Hide a comment div.
+   */
+  function hide(id) {
+    $('#ah' + id).hide();
+    $('#ao' + id).show();
+    var div = $('#sc' + id);
+    div.slideUp('fast', function() {
+      div.remove();
+    });
+  }
+
+  /**
+   * Perform an ajax request to get comments for a node
+   * and insert the comments into the comments tree.
+   */
+  function getComments(id) {
+    $.ajax({
+     type: 'GET',
+     url: opts.getCommentsURL,
+     data: {node: id},
+     success: function(data, textStatus, request) {
+       var ul = $('#cl' + id);
+       var speed = 100;
+       $('#cf' + id)
+         .find('textarea[name="proposal"]')
+         .data('source', data.source);
+
+       if (data.comments.length === 0) {
+         ul.html('<li>No comments yet.</li>');
+         ul.data('empty', true);
+       } else {
+         // If there are comments, sort them and put them in the list.
+         var comments = sortComments(data.comments);
+         speed = data.comments.length * 100;
+         appendComments(comments, ul);
+         ul.data('empty', false);
+       }
+       $('#cn' + id).slideUp(speed + 200);
+       ul.slideDown(speed);
+     },
+     error: function(request, textStatus, error) {
+       showError('Oops, there was a problem retrieving the comments.');
+     },
+     dataType: 'json'
+    });
+  }
+
+  /**
+   * Add a comment via ajax and insert the comment into the comment tree.
+   */
+  function addComment(form) {
+    var node_id = form.find('input[name="node"]').val();
+    var parent_id = form.find('input[name="parent"]').val();
+    var text = form.find('textarea[name="comment"]').val();
+    var proposal = form.find('textarea[name="proposal"]').val();
+
+    if (text == '') {
+      showError('Please enter a comment.');
+      return;
+    }
+
+    // Disable the form that is being submitted.
+    form.find('textarea,input').attr('disabled', 'disabled');
+
+    // Send the comment to the server.
+    $.ajax({
+      type: "POST",
+      url: opts.addCommentURL,
+      dataType: 'json',
+      data: {
+        node: node_id,
+        parent: parent_id,
+        text: text,
+        proposal: proposal
+      },
+      success: function(data, textStatus, error) {
+        // Reset the form.
+        if (node_id) {
+          hideProposeChange(node_id);
+        }
+        form.find('textarea')
+          .val('')
+          .add(form.find('input'))
+          .removeAttr('disabled');
+	var ul = $('#cl' + (node_id || parent_id));
+        if (ul.data('empty')) {
+          $(ul).empty();
+          ul.data('empty', false);
+        }
+        insertComment(data.comment);
+        var ao = $('#ao' + node_id);
+        ao.find('img').attr({'src': opts.commentBrightImage});
+        if (node_id) {
+          // if this was a "root" comment, remove the commenting box
+          // (the user can get it back by reopening the comment popup)
+          $('#ca' + node_id).slideUp();
+        }
+      },
+      error: function(request, textStatus, error) {
+        form.find('textarea,input').removeAttr('disabled');
+        showError('Oops, there was a problem adding the comment.');
+      }
+    });
+  }
+
+  /**
+   * Recursively append comments to the main comment list and children
+   * lists, creating the comment tree.
+   */
+  function appendComments(comments, ul) {
+    $.each(comments, function() {
+      var div = createCommentDiv(this);
+      ul.append($(document.createElement('li')).html(div));
+      appendComments(this.children, div.find('ul.comment-children'));
+      // To avoid stagnating data, don't store the comments children in data.
+      this.children = null;
+      div.data('comment', this);
+    });
+  }
+
+  /**
+   * After adding a new comment, it must be inserted in the correct
+   * location in the comment tree.
+   */
+  function insertComment(comment) {
+    var div = createCommentDiv(comment);
+
+    // To avoid stagnating data, don't store the comments children in data.
+    comment.children = null;
+    div.data('comment', comment);
+
+    var ul = $('#cl' + (comment.node || comment.parent));
+    var siblings = getChildren(ul);
+
+    var li = $(document.createElement('li'));
+    li.hide();
+
+    // Determine where in the parents children list to insert this comment.
+    for(i=0; i < siblings.length; i++) {
+      if (comp(comment, siblings[i]) <= 0) {
+        $('#cd' + siblings[i].id)
+          .parent()
+          .before(li.html(div));
+        li.slideDown('fast');
+        return;
+      }
+    }
+
+    // If we get here, this comment rates lower than all the others,
+    // or it is the only comment in the list.
+    ul.append(li.html(div));
+    li.slideDown('fast');
+  }
+
+  function acceptComment(id) {
+    $.ajax({
+      type: 'POST',
+      url: opts.acceptCommentURL,
+      data: {id: id},
+      success: function(data, textStatus, request) {
+        $('#cm' + id).fadeOut('fast');
+        $('#cd' + id).removeClass('moderate');
+      },
+      error: function(request, textStatus, error) {
+        showError('Oops, there was a problem accepting the comment.');
+      }
+    });
+  }
+
+  function deleteComment(id) {
+    $.ajax({
+      type: 'POST',
+      url: opts.deleteCommentURL,
+      data: {id: id},
+      success: function(data, textStatus, request) {
+        var div = $('#cd' + id);
+        if (data == 'delete') {
+          // Moderator mode: remove the comment and all children immediately
+          div.slideUp('fast', function() {
+            div.remove();
+          });
+          return;
+        }
+        // User mode: only mark the comment as deleted
+        div
+          .find('span.user-id:first')
+          .text('[deleted]').end()
+          .find('div.comment-text:first')
+          .text('[deleted]').end()
+          .find('#cm' + id + ', #dc' + id + ', #ac' + id + ', #rc' + id +
+                ', #sp' + id + ', #hp' + id + ', #cr' + id + ', #rl' + id)
+          .remove();
+        var comment = div.data('comment');
+        comment.username = '[deleted]';
+        comment.text = '[deleted]';
+        div.data('comment', comment);
+      },
+      error: function(request, textStatus, error) {
+        showError('Oops, there was a problem deleting the comment.');
+      }
+    });
+  }
+
+  function showProposal(id) {
+    $('#sp' + id).hide();
+    $('#hp' + id).show();
+    $('#pr' + id).slideDown('fast');
+  }
+
+  function hideProposal(id) {
+    $('#hp' + id).hide();
+    $('#sp' + id).show();
+    $('#pr' + id).slideUp('fast');
+  }
+
+  function showProposeChange(id) {
+    $('#pc' + id).hide();
+    $('#hc' + id).show();
+    var textarea = $('#pt' + id);
+    textarea.val(textarea.data('source'));
+    $.fn.autogrow.resize(textarea[0]);
+    textarea.slideDown('fast');
+  }
+
+  function hideProposeChange(id) {
+    $('#hc' + id).hide();
+    $('#pc' + id).show();
+    var textarea = $('#pt' + id);
+    textarea.val('').removeAttr('disabled');
+    textarea.slideUp('fast');
+  }
+
+  function toggleCommentMarkupBox(id) {
+    $('#mb' + id).toggle();
+  }
+
+  /** Handle when the user clicks on a sort by link. */
+  function handleReSort(link) {
+    var classes = link.attr('class').split(/\s+/);
+    for (var i=0; i<classes.length; i++) {
+      if (classes[i] != 'sort-option') {
+	by = classes[i].substring(2);
+      }
+    }
+    setComparator();
+    // Save/update the sortBy cookie.
+    var expiration = new Date();
+    expiration.setDate(expiration.getDate() + 365);
+    document.cookie= 'sortBy=' + escape(by) +
+                     ';expires=' + expiration.toUTCString();
+    $('ul.comment-ul').each(function(index, ul) {
+      var comments = getChildren($(ul), true);
+      comments = sortComments(comments);
+      appendComments(comments, $(ul).empty());
+    });
+  }
+
+  /**
+   * Function to process a vote when a user clicks an arrow.
+   */
+  function handleVote(link) {
+    if (!opts.voting) {
+      showError("You'll need to login to vote.");
+      return;
+    }
+
+    var id = link.attr('id');
+    if (!id) {
+      // Didn't click on one of the voting arrows.
+      return;
+    }
+    // If it is an unvote, the new vote value is 0,
+    // Otherwise it's 1 for an upvote, or -1 for a downvote.
+    var value = 0;
+    if (id.charAt(1) != 'u') {
+      value = id.charAt(0) == 'u' ? 1 : -1;
+    }
+    // The data to be sent to the server.
+    var d = {
+      comment_id: id.substring(2),
+      value: value
+    };
+
+    // Swap the vote and unvote links.
+    link.hide();
+    $('#' + id.charAt(0) + (id.charAt(1) == 'u' ? 'v' : 'u') + d.comment_id)
+      .show();
+
+    // The div the comment is displayed in.
+    var div = $('div#cd' + d.comment_id);
+    var data = div.data('comment');
+
+    // If this is not an unvote, and the other vote arrow has
+    // already been pressed, unpress it.
+    if ((d.value !== 0) && (data.vote === d.value * -1)) {
+      $('#' + (d.value == 1 ? 'd' : 'u') + 'u' + d.comment_id).hide();
+      $('#' + (d.value == 1 ? 'd' : 'u') + 'v' + d.comment_id).show();
+    }
+
+    // Update the comments rating in the local data.
+    data.rating += (data.vote === 0) ? d.value : (d.value - data.vote);
+    data.vote = d.value;
+    div.data('comment', data);
+
+    // Change the rating text.
+    div.find('.rating:first')
+      .text(data.rating + ' point' + (data.rating == 1 ? '' : 's'));
+
+    // Send the vote information to the server.
+    $.ajax({
+      type: "POST",
+      url: opts.processVoteURL,
+      data: d,
+      error: function(request, textStatus, error) {
+        showError('Oops, there was a problem casting that vote.');
+      }
+    });
+  }
+
+  /**
+   * Open a reply form used to reply to an existing comment.
+   */
+  function openReply(id) {
+    // Swap out the reply link for the hide link
+    $('#rl' + id).hide();
+    $('#cr' + id).show();
+
+    // Add the reply li to the children ul.
+    var div = $(renderTemplate(replyTemplate, {id: id})).hide();
+    $('#cl' + id)
+      .prepend(div)
+      // Setup the submit handler for the reply form.
+      .find('#rf' + id)
+      .submit(function(event) {
+        event.preventDefault();
+        addComment($('#rf' + id));
+        closeReply(id);
+      })
+      .find('input[type=button]')
+      .click(function() {
+        closeReply(id);
+      });
+    div.slideDown('fast', function() {
+      $('#rf' + id).find('textarea').focus();
+    });
+  }
+
+  /**
+   * Close the reply form opened with openReply.
+   */
+  function closeReply(id) {
+    // Remove the reply div from the DOM.
+    $('#rd' + id).slideUp('fast', function() {
+      $(this).remove();
+    });
+
+    // Swap out the hide link for the reply link
+    $('#cr' + id).hide();
+    $('#rl' + id).show();
+  }
+
+  /**
+   * Recursively sort a tree of comments using the comp comparator.
+   */
+  function sortComments(comments) {
+    comments.sort(comp);
+    $.each(comments, function() {
+      this.children = sortComments(this.children);
+    });
+    return comments;
+  }
+
+  /**
+   * Get the children comments from a ul. If recursive is true,
+   * recursively include childrens' children.
+   */
+  function getChildren(ul, recursive) {
+    var children = [];
+    ul.children().children("[id^='cd']")
+      .each(function() {
+        var comment = $(this).data('comment');
+        if (recursive)
+          comment.children = getChildren($(this).find('#cl' + comment.id), true);
+        children.push(comment);
+      });
+    return children;
+  }
+
+  /** Create a div to display a comment in. */
+  function createCommentDiv(comment) {
+    if (!comment.displayed && !opts.moderator) {
+      return $('<div class="moderate">Thank you!  Your comment will show up '
+               + 'once it is has been approved by a moderator.</div>');
+    }
+    // Prettify the comment rating.
+    comment.pretty_rating = comment.rating + ' point' +
+      (comment.rating == 1 ? '' : 's');
+    // Make a class (for displaying not yet moderated comments differently)
+    comment.css_class = comment.displayed ? '' : ' moderate';
+    // Create a div for this comment.
+    var context = $.extend({}, opts, comment);
+    var div = $(renderTemplate(commentTemplate, context));
+
+    // If the user has voted on this comment, highlight the correct arrow.
+    if (comment.vote) {
+      var direction = (comment.vote == 1) ? 'u' : 'd';
+      div.find('#' + direction + 'v' + comment.id).hide();
+      div.find('#' + direction + 'u' + comment.id).show();
+    }
+
+    if (opts.moderator || comment.text != '[deleted]') {
+      div.find('a.reply').show();
+      if (comment.proposal_diff)
+        div.find('#sp' + comment.id).show();
+      if (opts.moderator && !comment.displayed)
+        div.find('#cm' + comment.id).show();
+      if (opts.moderator || (opts.username == comment.username))
+        div.find('#dc' + comment.id).show();
+    }
+    return div;
+  }
+
+  /**
+   * A simple template renderer. Placeholders such as <%id%> are replaced
+   * by context['id'] with items being escaped. Placeholders such as <#id#>
+   * are not escaped.
+   */
+  function renderTemplate(template, context) {
+    var esc = $(document.createElement('div'));
+
+    function handle(ph, escape) {
+      var cur = context;
+      $.each(ph.split('.'), function() {
+        cur = cur[this];
+      });
+      return escape ? esc.text(cur || "").html() : cur;
+    }
+
+    return template.replace(/<([%#])([\w\.]*)\1>/g, function() {
+      return handle(arguments[2], arguments[1] == '%' ? true : false);
+    });
+  }
+
+  /** Flash an error message briefly. */
+  function showError(message) {
+    $(document.createElement('div')).attr({'class': 'popup-error'})
+      .append($(document.createElement('div'))
+               .attr({'class': 'error-message'}).text(message))
+      .appendTo('body')
+      .fadeIn("slow")
+      .delay(2000)
+      .fadeOut("slow");
+  }
+
+  /** Add a link the user uses to open the comments popup. */
+  $.fn.comment = function() {
+    return this.each(function() {
+      var id = $(this).attr('id').substring(1);
+      var count = COMMENT_METADATA[id];
+      var title = count + ' comment' + (count == 1 ? '' : 's');
+      var image = count > 0 ? opts.commentBrightImage : opts.commentImage;
+      var addcls = count == 0 ? ' nocomment' : '';
+      $(this)
+        .append(
+          $(document.createElement('a')).attr({
+            href: '#',
+            'class': 'sphinx-comment-open' + addcls,
+            id: 'ao' + id
+          })
+            .append($(document.createElement('img')).attr({
+              src: image,
+              alt: 'comment',
+              title: title
+            }))
+            .click(function(event) {
+              event.preventDefault();
+              show($(this).attr('id').substring(2));
+            })
+        )
+        .append(
+          $(document.createElement('a')).attr({
+            href: '#',
+            'class': 'sphinx-comment-close hidden',
+            id: 'ah' + id
+          })
+            .append($(document.createElement('img')).attr({
+              src: opts.closeCommentImage,
+              alt: 'close',
+              title: 'close'
+            }))
+            .click(function(event) {
+              event.preventDefault();
+              hide($(this).attr('id').substring(2));
+            })
+        );
+    });
+  };
+
+  var opts = {
+    processVoteURL: '/_process_vote',
+    addCommentURL: '/_add_comment',
+    getCommentsURL: '/_get_comments',
+    acceptCommentURL: '/_accept_comment',
+    deleteCommentURL: '/_delete_comment',
+    commentImage: '/static/_static/comment.png',
+    closeCommentImage: '/static/_static/comment-close.png',
+    loadingImage: '/static/_static/ajax-loader.gif',
+    commentBrightImage: '/static/_static/comment-bright.png',
+    upArrow: '/static/_static/up.png',
+    downArrow: '/static/_static/down.png',
+    upArrowPressed: '/static/_static/up-pressed.png',
+    downArrowPressed: '/static/_static/down-pressed.png',
+    voting: false,
+    moderator: false
+  };
+
+  if (typeof COMMENT_OPTIONS != "undefined") {
+    opts = jQuery.extend(opts, COMMENT_OPTIONS);
+  }
+
+  var popupTemplate = '\
+    <div class="sphinx-comments" id="sc<%id%>">\
+      <p class="sort-options">\
+        Sort by:\
+        <a href="#" class="sort-option byrating">best rated</a>\
+        <a href="#" class="sort-option byascage">newest</a>\
+        <a href="#" class="sort-option byage">oldest</a>\
+      </p>\
+      <div class="comment-header">Comments</div>\
+      <div class="comment-loading" id="cn<%id%>">\
+        loading comments... <img src="<%loadingImage%>" alt="" /></div>\
+      <ul id="cl<%id%>" class="comment-ul"></ul>\
+      <div id="ca<%id%>">\
+      <p class="add-a-comment">Add a comment\
+        (<a href="#" class="comment-markup" id="ab<%id%>">markup</a>):</p>\
+      <div class="comment-markup-box" id="mb<%id%>">\
+        reStructured text markup: <i>*emph*</i>, <b>**strong**</b>, \
+        <code>``code``</code>, \
+        code blocks: <code>::</code> and an indented block after blank line</div>\
+      <form method="post" id="cf<%id%>" class="comment-form" action="">\
+        <textarea name="comment" cols="80"></textarea>\
+        <p class="propose-button">\
+          <a href="#" id="pc<%id%>" class="show-propose-change">\
+            Propose a change &#9657;\
+          </a>\
+          <a href="#" id="hc<%id%>" class="hide-propose-change">\
+            Propose a change &#9663;\
+          </a>\
+        </p>\
+        <textarea name="proposal" id="pt<%id%>" cols="80"\
+                  spellcheck="false"></textarea>\
+        <input type="submit" value="Add comment" />\
+        <input type="hidden" name="node" value="<%id%>" />\
+        <input type="hidden" name="parent" value="" />\
+      </form>\
+      </div>\
+    </div>';
+
+  var commentTemplate = '\
+    <div id="cd<%id%>" class="sphinx-comment<%css_class%>">\
+      <div class="vote">\
+        <div class="arrow">\
+          <a href="#" id="uv<%id%>" class="vote" title="vote up">\
+            <img src="<%upArrow%>" />\
+          </a>\
+          <a href="#" id="uu<%id%>" class="un vote" title="vote up">\
+            <img src="<%upArrowPressed%>" />\
+          </a>\
+        </div>\
+        <div class="arrow">\
+          <a href="#" id="dv<%id%>" class="vote" title="vote down">\
+            <img src="<%downArrow%>" id="da<%id%>" />\
+          </a>\
+          <a href="#" id="du<%id%>" class="un vote" title="vote down">\
+            <img src="<%downArrowPressed%>" />\
+          </a>\
+        </div>\
+      </div>\
+      <div class="comment-content">\
+        <p class="tagline comment">\
+          <span class="user-id"><%username%></span>\
+          <span class="rating"><%pretty_rating%></span>\
+          <span class="delta"><%time.delta%></span>\
+        </p>\
+        <div class="comment-text comment"><#text#></div>\
+        <p class="comment-opts comment">\
+          <a href="#" class="reply hidden" id="rl<%id%>">reply &#9657;</a>\
+          <a href="#" class="close-reply" id="cr<%id%>">reply &#9663;</a>\
+          <a href="#" id="sp<%id%>" class="show-proposal">proposal &#9657;</a>\
+          <a href="#" id="hp<%id%>" class="hide-proposal">proposal &#9663;</a>\
+          <a href="#" id="dc<%id%>" class="delete-comment hidden">delete</a>\
+          <span id="cm<%id%>" class="moderation hidden">\
+            <a href="#" id="ac<%id%>" class="accept-comment">accept</a>\
+          </span>\
+        </p>\
+        <pre class="proposal" id="pr<%id%>">\
+<#proposal_diff#>\
+        </pre>\
+          <ul class="comment-children" id="cl<%id%>"></ul>\
+        </div>\
+        <div class="clearleft"></div>\
+      </div>\
+    </div>';
+
+  var replyTemplate = '\
+    <li>\
+      <div class="reply-div" id="rd<%id%>">\
+        <form id="rf<%id%>">\
+          <textarea name="comment" cols="80"></textarea>\
+          <input type="submit" value="Add reply" />\
+          <input type="button" value="Cancel" />\
+          <input type="hidden" name="parent" value="<%id%>" />\
+          <input type="hidden" name="node" value="" />\
+        </form>\
+      </div>\
+    </li>';
+
+  $(document).ready(function() {
+    init();
+  });
+})(jQuery);
+
+$(document).ready(function() {
+  // add comment anchors for all paragraphs that are commentable
+  $('.sphinx-has-comment').comment();
+
+  // highlight search words in search results
+  $("div.context").each(function() {
+    var params = $.getQueryParameters();
+    var terms = (params.q) ? params.q[0].split(/\s+/) : [];
+    var result = $(this);
+    $.each(terms, function() {
+      result.highlightText(this.toLowerCase(), 'highlighted');
+    });
+  });
+
+  // directly open comment window if requested
+  var anchor = document.location.hash;
+  if (anchor.substring(0, 9) == '#comment-') {
+    $('#ao' + anchor.substring(9)).click();
+    document.location.hash = '#s' + anchor.substring(9);
+  }
+});

+ 436 - 0
doc/_build/html/actionlanguage.html

@@ -0,0 +1,436 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Action Language &#8212; Modelverse 0.4.0 documentation</title>
+    
+    <link rel="stylesheet" href="_static/classic.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    './',
+        VERSION:     '0.4.0',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="Modelverse 0.4.0 documentation" href="index.html" />
+    <link rel="next" title="Modelling Language" href="modellanguage.html" />
+    <link rel="prev" title="How to run" href="howto.html" /> 
+  </head>
+  <body role="document">
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="modellanguage.html" title="Modelling Language"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="howto.html" title="How to run"
+             accesskey="P">previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body" role="main">
+            
+  <div class="section" id="action-language">
+<h1>Action Language<a class="headerlink" href="#action-language" title="Permalink to this headline">¶</a></h1>
+<p>The primary language of the Modelverse, is its action language.
+This language serves as a nicer representation of the underlying Modelverse Graph Language, which is stored as a graph.
+The action language gets parsed by the parser, resulting in a kind of abstract syntax graph.
+This abstract syntax graph highly resembles an executable graph in the Modelverse Graph Language.</p>
+<p>Users will mainly use this language to write actions and constraints, but maybe also to implement their own interfaces, or override core functionality of the Modelverse.</p>
+<div class="admonition warning">
+<p class="first admonition-title">Warning</p>
+<p class="last">The current parser is unable to handle whitespaces in a general way.
+As such, all indentation needs to be done using tabs, and the difference needs to be exactly 1.
+This is different from Python, where tabs and whitespaces can be mixed, and the number can even vary.</p>
+</div>
+<div class="section" id="files">
+<h2>Files<a class="headerlink" href="#files" title="Permalink to this headline">¶</a></h2>
+<p>There are two kinds of files: code files, and headers.
+This distinction is similar to C and related languages.
+Code in header files will always be copied throughout all including files.
+As such, it is a good idea to have header files which declare the signatures of functions, but leave the actual implementation to the code files.
+Code files do not need to import the headers they are implementing: all variable names are automatically shared.</p>
+</div>
+<div class="section" id="language-description">
+<h2>Language description<a class="headerlink" href="#language-description" title="Permalink to this headline">¶</a></h2>
+<p>The language is inspired by Python syntax, and highly resembles it.
+Nonetheless, it is a lot simpler.
+In the remainder of this subsection, we go over the different language constructs.</p>
+<div class="section" id="if">
+<h3>If<a class="headerlink" href="#if" title="Permalink to this headline">¶</a></h3>
+<p>The IF construct is similar to that found in other languages.
+Its structure is as follows:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="k">if</span> <span class="n">condition1</span><span class="p">:</span>
+   <span class="n">do_when_condition1</span>
+<span class="k">elif</span> <span class="n">condition2</span><span class="p">:</span>
+   <span class="n">do_when_condition2</span>
+<span class="k">else</span><span class="p">:</span>
+   <span class="n">do_otherwise</span>
+</pre></div>
+</div>
+<p>Each condition can be an expression.
+The code blocks can be any other kind of code.
+Just like Python, indentation is the only way to structure code.
+Unlike Python, only tabs are allowed (thus no space), and the number of tabs must be exactly one higher for a deeper block.</p>
+<p>The presence of an &#8220;elif&#8221; and &#8220;else&#8221; is optional.</p>
+</div>
+<div class="section" id="while">
+<h3>While<a class="headerlink" href="#while" title="Permalink to this headline">¶</a></h3>
+<p>The WHILE construct is similar to that found in other languages.
+Contrary to Python, there is no support for the &#8220;else&#8221; construct.
+Its structure is as follows:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="k">while</span> <span class="n">condition</span><span class="p">:</span>
+    <span class="n">action</span>
+</pre></div>
+</div>
+<p>Conditions and actions are similar to the If construct.</p>
+</div>
+<div class="section" id="break">
+<h3>Break<a class="headerlink" href="#break" title="Permalink to this headline">¶</a></h3>
+<p>Whereas this is supported in the Modelverse, the parser currently does not consider this keyword.</p>
+</div>
+<div class="section" id="continue">
+<h3>Continue<a class="headerlink" href="#continue" title="Permalink to this headline">¶</a></h3>
+<p>Whereas this is supported in the Modelverse, the parser currently does not consider this keyword.</p>
+</div>
+<div class="section" id="return">
+<h3>Return<a class="headerlink" href="#return" title="Permalink to this headline">¶</a></h3>
+<p>The RETURN construct is again similar to how it is expected.
+To prevent ambiguity in the grammar, an exclamation mark should follow after the expression to return.
+Its structure is as follows:</p>
+<div class="highlight-default"><div class="highlight"><pre>return expression!
+</pre></div>
+</div>
+<p>The expression can be any expression, similar to the condition in an If and While.</p>
+</div>
+<div class="section" id="function-call">
+<h3>Function call<a class="headerlink" href="#function-call" title="Permalink to this headline">¶</a></h3>
+<p>Function calls happen like usual, by appending an opening and closing parenthesis at the end.
+Its structure is as follows:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">my_function</span><span class="p">(</span><span class="n">argument_a</span><span class="p">,</span> <span class="n">argument_b</span><span class="p">)</span>
+</pre></div>
+</div>
+<p>Arguments can again be any kind of expression.
+Named parameters are not supported in the grammar, though the Modelverse can internally handle them.</p>
+</div>
+<div class="section" id="function-definition">
+<h3>Function definition<a class="headerlink" href="#function-definition" title="Permalink to this headline">¶</a></h3>
+<p>Defining a function makes the function available as a variable in the remainder of the context.
+Forward declaration is unnecessary: all function names are retrieved before going over the body of the functions.
+This makes mutual recursion easy.</p>
+<p>A function needs to define its return type, as well as the type of all its parameters.
+In case the type is unknown, or can be anything, <em>Element</em> can be used as a kind of &#8220;void pointer&#8221;.
+Its structure is as follows:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">Element</span> <span class="n">function</span> <span class="n">function_name</span><span class="p">(</span><span class="n">parameter_a</span> <span class="p">:</span> <span class="n">Integer</span><span class="p">):</span>
+    <span class="n">body_of_the_function</span>
+</pre></div>
+</div>
+<p>First comes the returntype, followed by the keyword &#8220;function&#8221;.
+Again, indentation needs to happen using tabs.</p>
+</div>
+<div class="section" id="assignment">
+<h3>Assignment<a class="headerlink" href="#assignment" title="Permalink to this headline">¶</a></h3>
+<p>Assignment is like usual.
+Its structure is:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">a</span> <span class="o">=</span> <span class="n">expression</span>
+</pre></div>
+</div>
+<p>This assumes that a is already defined.</p>
+</div>
+<div class="section" id="declaration">
+<h3>Declaration<a class="headerlink" href="#declaration" title="Permalink to this headline">¶</a></h3>
+<p>All variables used in the Modelverse need to be defined statically.
+Defining a variable reserves a part of the Modelverse State to hold the value for this value.
+As such, variables cannot be used if they are not defined.
+Additionally, a declared variable will have a type defined with it.
+Again, if the type can vary or is unknown, this can be <em>Element</em>.</p>
+<div class="admonition warning">
+<p class="first admonition-title">Warning</p>
+<p class="last">Contrary to other languages, declaring a variable does not equal defining the variable.
+Therefore, after a variable is declared, it can be used, but its contents will be non-existing.
+It is wise to always assign a value to a declared value right after declaration!</p>
+</div>
+<p>Its structure is as follows:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">String</span> <span class="n">abc</span>
+</pre></div>
+</div>
+<p>There are two kinds of declaration: local declaration, and global declaration.
+Local declarations happen in the current block of the code, and their references get removed when exiting the block.
+Global declarations have identically the same syntax, but are specified at the top level (<em>i.e.</em>, they have no tabs in front of them).
+Global declarations do not assign a value and are thus external references, to be defined in the future or by some other module.
+Sharing between modules is possible this way, as all global names are linked together when linking the application together.
+A global declaration that is never defined is flagged as invalid by the compiler and will prevent compilation.</p>
+</div>
+<div class="section" id="definition">
+<h3>Definition<a class="headerlink" href="#definition" title="Permalink to this headline">¶</a></h3>
+<p>Defining a variable is similar to a global declaration, but now there is an immediate assignment.
+Immediate assignment is only possible at the top level.
+Note that the assignment must be of a constant which requires no execution of functions or such.
+Also, it is impossible to assign the value of another variable.</p>
+<p>Its structure is as follows:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">String</span> <span class="n">abc</span> <span class="o">=</span> <span class="s">&quot;abc&quot;</span>
+</pre></div>
+</div>
+<p>It is possible that a definition does not yet know the value to assign, or is an empty element.
+To notify the other files that this is the defining element, use the import syntax to assign <em>?</em> to it:</p>
+<div class="highlight-default"><div class="highlight"><pre>Element abc = ?
+</pre></div>
+</div>
+<p>This results in the Modelverse creating an empty node as placeholder for a value.
+The value will now be defined and accessible.</p>
+</div>
+<div class="section" id="imports">
+<h3>Imports<a class="headerlink" href="#imports" title="Permalink to this headline">¶</a></h3>
+<p>Direct imports in the Modelverse are possible, but are not recommended for ordinary users.
+This syntax allows a variable to be bound to an absolute location in the Modelverse, which is resolved at compile time.
+The primary use case for this is the creation of bootstrap files, but it is also possible for other purposes.
+Use with care!</p>
+<p>Its structure is as follows:</p>
+<div class="highlight-default"><div class="highlight"><pre>String abc = ?path/in/modelverse
+</pre></div>
+</div>
+<p>A special case is when the path is empty, which indicates that a new (anonymous) node should be created for it:</p>
+<div class="highlight-default"><div class="highlight"><pre>Element abc = ?
+</pre></div>
+</div>
+</div>
+<div class="section" id="include">
+<h3>Include<a class="headerlink" href="#include" title="Permalink to this headline">¶</a></h3>
+<p>Other files can easily be included using the include syntax.
+This is a raw include: the contents of the file are just copied inside the file at that exact spot.
+Generally, you should only include <em>.alh</em> files, unless you know what you are doing.</p>
+</div>
+<div class="section" id="constants">
+<h3>Constants<a class="headerlink" href="#constants" title="Permalink to this headline">¶</a></h3>
+<p>The Modelverse supports a set of constants that can be used.
+All constants can be assigned in a definition of globals.</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="14%" />
+<col width="79%" />
+<col width="7%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Constant type</th>
+<th class="head">Values</th>
+<th class="head">Example</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td>Integer</td>
+<td>Any possible integer, either positive (no prefix) or negative (- prefix)</td>
+<td>1</td>
+</tr>
+<tr class="row-odd"><td>Float</td>
+<td>Any possible floating point value; scientific notation is not supported</td>
+<td>1.0</td>
+</tr>
+<tr class="row-even"><td>Boolean</td>
+<td>Either True or False</td>
+<td>True</td>
+</tr>
+<tr class="row-odd"><td>String</td>
+<td>Any possible string, enclosed with either double or single quotes</td>
+<td>&#8220;abc&#8221;</td>
+</tr>
+<tr class="row-even"><td>Action</td>
+<td>An action construct from the Modelverse, prefixed with an exclamation mark</td>
+<td>!If</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="operators">
+<h3>Operators<a class="headerlink" href="#operators" title="Permalink to this headline">¶</a></h3>
+<p>While operators are seemingly supported by the compiler, these are actually expanded to function calls to relevant functions.
+For example, <em>1 + 2</em>, is expanded to <em>integer_addition(1, 2)</em></p>
+</div>
+<div class="section" id="user-i-o">
+<h3>User I/O<a class="headerlink" href="#user-i-o" title="Permalink to this headline">¶</a></h3>
+<p>User input and output is done through the keyworded operations <em>input()</em> and <em>output(msg)</em>.
+<em>input()</em> returns the first message in the input queue of the current user.
+<em>output(msg)</em> places the value of the expression in the output queue of the current user.</p>
+<p>All I/O is done using queues: the value is only read and written to a specific place in the Modelverse.
+To actually read or write it at the client side, these special places should be accessed through dedicated Modelverse operations.</p>
+</div>
+</div>
+<div class="section" id="examples">
+<h2>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h2>
+<p>We now show some simple code fragments written in valid Action Language code.
+As this code is directly executable in the Modelverse, the main function is always called &#8220;main&#8221; and all includes are also present.
+We do not currently handle how to execute this code: this is explained further on.</p>
+<div class="section" id="fibonacci">
+<h3>Fibonacci<a class="headerlink" href="#fibonacci" title="Permalink to this headline">¶</a></h3>
+<p>The Fibonacci code is fairly simple.
+First, the primitives are imported to make sure that we know about all operations on primitives.
+Then, a function <em>fib</em> is defined, which will recursively compute the specified Fibonacci number.
+This is wrapped by a <em>main</em> function, which takes input from the user and outputs the result of the <em>fib</em> function.</p>
+<p>This code looks as follows:</p>
+<div class="highlight-default"><div class="highlight"><pre>include &quot;primitives.alh&quot;
+
+Integer function fib(param : Integer):
+    if (param &lt;= 2):
+        return 1!
+    else:
+        return fib(param - 1) + fib(param - 2)!
+
+Void function main():
+    while(True):
+        output(fib(input()))
+</pre></div>
+</div>
+</div>
+<div class="section" id="factorial">
+<h3>Factorial<a class="headerlink" href="#factorial" title="Permalink to this headline">¶</a></h3>
+<p>Similarly, the code for computing a factorial is given below:</p>
+<div class="highlight-default"><div class="highlight"><pre>include &quot;primitives.alh&quot;
+
+Integer function factorial(n : Integer):
+    if(n &lt;= 1):
+        return 1!
+    else:
+        return n * factorial(n - 1)!
+
+Void function main():
+    while(True):
+        output(factorial(input()))
+</pre></div>
+</div>
+</div>
+<div class="section" id="binary-to-decimal-converter">
+<h3>Binary to decimal converter<a class="headerlink" href="#binary-to-decimal-converter" title="Permalink to this headline">¶</a></h3>
+<p>A simple binary to decimal converter is given below:</p>
+<div class="highlight-default"><div class="highlight"><pre>include &quot;primitives.alh&quot;
+
+Integer function b2d(param : String):
+    Integer value
+    value = 0
+    Integer length
+    length = string_len(param)
+    Integer counter
+    counter = integer_subtraction(length, 1)
+    Integer accumul
+    accumul = 1
+
+    while (counter &gt;= 0):
+        if (string_get(param, counter) == &quot;1&quot;):
+            value = integer_addition(value, accumul)
+        accumul = integer_multiplication(accumul, 2)
+        counter = integer_subtraction(counter, 1)
+
+    return value!
+
+Void function main():
+    while(True):
+        output(b2d(input()))
+</pre></div>
+</div>
+</div>
+</div>
+</div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
+        <div class="sphinxsidebarwrapper">
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Action Language</a><ul>
+<li><a class="reference internal" href="#files">Files</a></li>
+<li><a class="reference internal" href="#language-description">Language description</a><ul>
+<li><a class="reference internal" href="#if">If</a></li>
+<li><a class="reference internal" href="#while">While</a></li>
+<li><a class="reference internal" href="#break">Break</a></li>
+<li><a class="reference internal" href="#continue">Continue</a></li>
+<li><a class="reference internal" href="#return">Return</a></li>
+<li><a class="reference internal" href="#function-call">Function call</a></li>
+<li><a class="reference internal" href="#function-definition">Function definition</a></li>
+<li><a class="reference internal" href="#assignment">Assignment</a></li>
+<li><a class="reference internal" href="#declaration">Declaration</a></li>
+<li><a class="reference internal" href="#definition">Definition</a></li>
+<li><a class="reference internal" href="#imports">Imports</a></li>
+<li><a class="reference internal" href="#include">Include</a></li>
+<li><a class="reference internal" href="#constants">Constants</a></li>
+<li><a class="reference internal" href="#operators">Operators</a></li>
+<li><a class="reference internal" href="#user-i-o">User I/O</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#examples">Examples</a><ul>
+<li><a class="reference internal" href="#fibonacci">Fibonacci</a></li>
+<li><a class="reference internal" href="#factorial">Factorial</a></li>
+<li><a class="reference internal" href="#binary-to-decimal-converter">Binary to decimal converter</a></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="howto.html"
+                        title="previous chapter">How to run</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="modellanguage.html"
+                        title="next chapter">Modelling Language</a></p>
+  <div role="note" aria-label="source link">
+    <h3>This Page</h3>
+    <ul class="this-page-menu">
+      <li><a href="_sources/actionlanguage.txt"
+            rel="nofollow">Show Source</a></li>
+    </ul>
+   </div>
+<div id="searchbox" style="display: none" role="search">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <div><input type="text" name="q" /></div>
+      <div><input type="submit" value="Go" /></div>
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="modellanguage.html" title="Modelling Language"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="howto.html" title="How to run"
+             >previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>
+    <div class="footer" role="contentinfo">
+        &#169; Copyright 2016, Yentl Van Tendeloo.
+      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.6.
+    </div>
+  </body>
+</html>

+ 130 - 0
doc/_build/html/advanced.html

@@ -0,0 +1,130 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Advanced examples &#8212; Modelverse 0.4.0 documentation</title>
+    
+    <link rel="stylesheet" href="_static/classic.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    './',
+        VERSION:     '0.4.0',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="Modelverse 0.4.0 documentation" href="index.html" />
+    <link rel="next" title="Common problems and solutions" href="problems.html" />
+    <link rel="prev" title="Examples" href="examples.html" /> 
+  </head>
+  <body role="document">
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="problems.html" title="Common problems and solutions"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="examples.html" title="Examples"
+             accesskey="P">previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body" role="main">
+            
+  <div class="section" id="advanced-examples">
+<h1>Advanced examples<a class="headerlink" href="#advanced-examples" title="Permalink to this headline">¶</a></h1>
+<p>These advanced examples show you how the core algorithms of the Modelverse are implemented and how you can potentially modify them.
+This part is still TODO, since this is probably not of interest to you.</p>
+<div class="section" id="inheritance-semantics">
+<h2>Inheritance Semantics<a class="headerlink" href="#inheritance-semantics" title="Permalink to this headline">¶</a></h2>
+</div>
+<div class="section" id="instantiation-semantics">
+<h2>Instantiation Semantics<a class="headerlink" href="#instantiation-semantics" title="Permalink to this headline">¶</a></h2>
+</div>
+<div class="section" id="conformance-semantics">
+<h2>Conformance Semantics<a class="headerlink" href="#conformance-semantics" title="Permalink to this headline">¶</a></h2>
+</div>
+</div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
+        <div class="sphinxsidebarwrapper">
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Advanced examples</a><ul>
+<li><a class="reference internal" href="#inheritance-semantics">Inheritance Semantics</a></li>
+<li><a class="reference internal" href="#instantiation-semantics">Instantiation Semantics</a></li>
+<li><a class="reference internal" href="#conformance-semantics">Conformance Semantics</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="examples.html"
+                        title="previous chapter">Examples</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="problems.html"
+                        title="next chapter">Common problems and solutions</a></p>
+  <div role="note" aria-label="source link">
+    <h3>This Page</h3>
+    <ul class="this-page-menu">
+      <li><a href="_sources/advanced.txt"
+            rel="nofollow">Show Source</a></li>
+    </ul>
+   </div>
+<div id="searchbox" style="display: none" role="search">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <div><input type="text" name="q" /></div>
+      <div><input type="submit" value="Go" /></div>
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="problems.html" title="Common problems and solutions"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="examples.html" title="Examples"
+             >previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>
+    <div class="footer" role="contentinfo">
+        &#169; Copyright 2016, Yentl Van Tendeloo.
+      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.6.
+    </div>
+  </body>
+</html>

+ 139 - 0
doc/_build/html/communication_models.html

@@ -0,0 +1,139 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Communication models &#8212; Modelverse 0.4.0 documentation</title>
+    
+    <link rel="stylesheet" href="_static/classic.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    './',
+        VERSION:     '0.4.0',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="Modelverse 0.4.0 documentation" href="index.html" />
+    <link rel="prev" title="Interface description" href="interface.html" /> 
+  </head>
+  <body role="document">
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="interface.html" title="Interface description"
+             accesskey="P">previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body" role="main">
+            
+  <div class="section" id="communication-models">
+<h1>Communication models<a class="headerlink" href="#communication-models" title="Permalink to this headline">¶</a></h1>
+<p>The network communication in the Modelverse builds on top of the raw socket implementation of Python.
+Whereas we use normal HTTP requests, we explicitly opted not to use these libraries.
+Many of these libraries hide important implementation details, such as how successive requests are handled (sequential, threaded, ...), whether or not to keep connections open and reuse them, which HTTP version to implement, and so on.
+As the HTTP protocol is a simple protocol, we reimplemented it completely in SCCD (StateCharts and Class Diagrams).</p>
+<p>There are two network components: a server in the MvS, and a server and client in the MvK.</p>
+<div class="section" id="mvs-server">
+<h2>MvS server<a class="headerlink" href="#mvs-server" title="Permalink to this headline">¶</a></h2>
+<img alt="_images/mvs_server.svg" src="_images/mvs_server.svg" /><p>The MvS server mainly just waits for incoming HTTP requests and presents the message to the MvS interface itself.
+Each part of the processing happens in a seperate orthogonal component, but in all cases, processing happens sequentially, and buffers are implemented in between each layer.
+This way, we can be certain that invocations on the MvS will always happen sequentially.</p>
+<p>The statechart consists of two parts.</p>
+<p>The topmost part is the HTTP server itself, which waits from messages from the sockets.
+When it starts up, a socket is created that listens to incoming connections.
+Messages from the socket are then processed.
+Apart from setting up the sockets, this component serializes all requests that get sent to the MvS: events are placed in a queue, and are only executed on the MvS when it has finished processing the previous request.</p>
+<p>The bottommost part is the socket server, which wraps around the socket and keeps fetching from the socket until it gets a complete HTTP request.
+The HTTP request is then split from the other data on the socket, and forwarded as a single request to the HTTP server.
+We explicitly need to check and split HTTP requests, as our protocol allows users to bundle multiple HTTP requests simultaneously.
+These requests will just come one after the other, so the socket buffer might contain two messages at the same time, or even fragments of a second request.
+A message is forwarded as soon as it is completely reconstructed.</p>
+</div>
+<div class="section" id="mvk-server">
+<h2>MvK server<a class="headerlink" href="#mvk-server" title="Permalink to this headline">¶</a></h2>
+<img alt="_images/mvk_server.svg" src="_images/mvk_server.svg" /><div class="admonition note">
+<p class="first admonition-title">Note</p>
+<p class="last">This figure shows the intended model, not the optimized model.
+For performance reasons, many of these parts are merged together in the <em>run_local_modelverse.py</em> script.
+As a result, it only implements the <em>MvKController</em>, <em>Server</em>, and <em>Socket</em> classes.
+A more elaborate statechart implementation also exists, which does implements this whole figure.</p>
+</div>
+</div>
+</div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
+        <div class="sphinxsidebarwrapper">
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Communication models</a><ul>
+<li><a class="reference internal" href="#mvs-server">MvS server</a></li>
+<li><a class="reference internal" href="#mvk-server">MvK server</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="interface.html"
+                        title="previous chapter">Interface description</a></p>
+  <div role="note" aria-label="source link">
+    <h3>This Page</h3>
+    <ul class="this-page-menu">
+      <li><a href="_sources/communication_models.txt"
+            rel="nofollow">Show Source</a></li>
+    </ul>
+   </div>
+<div id="searchbox" style="display: none" role="search">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <div><input type="text" name="q" /></div>
+      <div><input type="submit" value="Go" /></div>
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="interface.html" title="Interface description"
+             >previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>
+    <div class="footer" role="contentinfo">
+        &#169; Copyright 2016, Yentl Van Tendeloo.
+      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.6.
+    </div>
+  </body>
+</html>

+ 153 - 0
doc/_build/html/components.html

@@ -0,0 +1,153 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Modelverse components &#8212; Modelverse 0.4.0 documentation</title>
+    
+    <link rel="stylesheet" href="_static/classic.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    './',
+        VERSION:     '0.4.0',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="Modelverse 0.4.0 documentation" href="index.html" />
+    <link rel="next" title="How to run" href="howto.html" />
+    <link rel="prev" title="Installation" href="installation.html" /> 
+  </head>
+  <body role="document">
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="howto.html" title="How to run"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="installation.html" title="Installation"
+             accesskey="P">previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body" role="main">
+            
+  <div class="section" id="modelverse-components">
+<h1>Modelverse components<a class="headerlink" href="#modelverse-components" title="Permalink to this headline">¶</a></h1>
+<p>The Modelverse consists of three individual projects, which are linked together to construct the Modelverse.
+Each of these projects stands alone and has its own concerns.
+A socket interface to communicate with the other components is provided.
+By using sockets, it becomes possible to switch everything about the implementation, even the implementation language, without endangering interoperability.</p>
+<p>The three projects are:
+1. Modelverse State
+2. Modelverse Kernel
+3. Modelverse Interface</p>
+<img alt="_images/overview.svg" src="_images/overview.svg" /><div class="section" id="modelverse-state-mvs">
+<h2>Modelverse State (MvS)<a class="headerlink" href="#modelverse-state-mvs" title="Permalink to this headline">¶</a></h2>
+<p>The Modelverse State implements the data storage features of the Modelverse.
+To the Modelverse State, all data needs to be representable as a graph, which it will manipulate.</p>
+<p>All basic, and some composite, operations are implemented on this graph, such as creating nodes and edges, reading them, and deleting them.</p>
+</div>
+<div class="section" id="modelverse-kernel-mvk">
+<h2>Modelverse Kernel (MvK)<a class="headerlink" href="#modelverse-kernel-mvk" title="Permalink to this headline">¶</a></h2>
+<p>The Modelverse Kernel communicates with the MvS and interprets its data.
+The Modelverse Kernel has no way of storing data, except by sending it to the MvS for storage.
+Through this architecture, the MvK becomes completely stateless and easily replacable.</p>
+<p>For the MvK, a set of rules is defined which tell it how to interpret the graph in the MvS.
+Complex programs can be written by encoding the program as a graph, and letting the MvK interpret it.</p>
+<p>To allow for maximal flexibility, the MvK can never expose the users to the internal identifier of the MvS, which the MvK uses.
+This allows the MvS to internally restructure itself without having to worry about stale references elsewhere.</p>
+</div>
+<div class="section" id="modelverse-interface-mvi">
+<h2>Modelverse Interface (MvI)<a class="headerlink" href="#modelverse-interface-mvi" title="Permalink to this headline">¶</a></h2>
+<p>The Modelverse Interface is the part that most users will be using.
+It presents a textual or graphical interface to the Modelverse itself.
+Depending on the interface, the MvK and MvS will serve only as a repository (heavy client), or they serve as the tool itself (thin client).
+Either way, the communication is identical, just the granularity differs, and the place where the algorithms are implemented.</p>
+<p>Traditionally, the MvI is a compiler that compiles some code to either a graph, or operations for the MvK.
+This can, however, be any possible kind of tool, or even combination of multiple tools.
+For example, a graphical tool could serve as an interface to the Modelverse, where it just processes the graphical events and sends the desired operations (such as creating an element) to the Modelverse.</p>
+</div>
+</div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
+        <div class="sphinxsidebarwrapper">
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Modelverse components</a><ul>
+<li><a class="reference internal" href="#modelverse-state-mvs">Modelverse State (MvS)</a></li>
+<li><a class="reference internal" href="#modelverse-kernel-mvk">Modelverse Kernel (MvK)</a></li>
+<li><a class="reference internal" href="#modelverse-interface-mvi">Modelverse Interface (MvI)</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="installation.html"
+                        title="previous chapter">Installation</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="howto.html"
+                        title="next chapter">How to run</a></p>
+  <div role="note" aria-label="source link">
+    <h3>This Page</h3>
+    <ul class="this-page-menu">
+      <li><a href="_sources/components.txt"
+            rel="nofollow">Show Source</a></li>
+    </ul>
+   </div>
+<div id="searchbox" style="display: none" role="search">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <div><input type="text" name="q" /></div>
+      <div><input type="submit" value="Go" /></div>
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="howto.html" title="How to run"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="installation.html" title="Installation"
+             >previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>
+    <div class="footer" role="contentinfo">
+        &#169; Copyright 2016, Yentl Van Tendeloo.
+      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.6.
+    </div>
+  </body>
+</html>

Разница между файлами не показана из-за своего большого размера
+ 573 - 0
doc/_build/html/examples.html


+ 89 - 0
doc/_build/html/genindex.html

@@ -0,0 +1,89 @@
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Index &#8212; Modelverse 0.4.0 documentation</title>
+    
+    <link rel="stylesheet" href="_static/classic.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    './',
+        VERSION:     '0.4.0',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="Modelverse 0.4.0 documentation" href="index.html" /> 
+  </head>
+  <body role="document">
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="#" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body" role="main">
+            
+
+<h1 id="index">Index</h1>
+
+<div class="genindex-jumpbox">
+ 
+</div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
+        <div class="sphinxsidebarwrapper">
+
+   
+
+<div id="searchbox" style="display: none" role="search">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <div><input type="text" name="q" /></div>
+      <div><input type="submit" value="Go" /></div>
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="#" title="General Index"
+             >index</a></li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>
+    <div class="footer" role="contentinfo">
+        &#169; Copyright 2016, Yentl Van Tendeloo.
+      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.6.
+    </div>
+  </body>
+</html>

+ 405 - 0
doc/_build/html/howto.html

@@ -0,0 +1,405 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>How to run &#8212; Modelverse 0.4.0 documentation</title>
+    
+    <link rel="stylesheet" href="_static/classic.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    './',
+        VERSION:     '0.4.0',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="Modelverse 0.4.0 documentation" href="index.html" />
+    <link rel="next" title="Action Language" href="actionlanguage.html" />
+    <link rel="prev" title="Modelverse components" href="components.html" /> 
+  </head>
+  <body role="document">
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="actionlanguage.html" title="Action Language"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="components.html" title="Modelverse components"
+             accesskey="P">previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body" role="main">
+            
+  <div class="section" id="how-to-run">
+<h1>How to run<a class="headerlink" href="#how-to-run" title="Permalink to this headline">¶</a></h1>
+<p>Running the Modelverse is all done through the use of scripts to coordinate the three different projects.</p>
+<p>The following scripts are included by default.</p>
+<div class="section" id="check-objects-py">
+<h2>check_objects.py<a class="headerlink" href="#check-objects-py" title="Permalink to this headline">¶</a></h2>
+<p>Checks whether all compiled objects can be found, and if their symbol table does not contain undefined references.
+This script cannot be executed directly and is only a helper.</p>
+</div>
+<div class="section" id="compile-py">
+<h2>compile.py<a class="headerlink" href="#compile-py" title="Permalink to this headline">¶</a></h2>
+<p>Compiles the provided code with the selected mode.
+This should also not be called by end-users, though it is possible.</p>
+<p>Invocation:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">python</span> <span class="n">scripts</span><span class="o">/</span><span class="nb">compile</span><span class="o">.</span><span class="n">py</span> <span class="n">address</span> <span class="n">file</span> <span class="n">username</span> <span class="nb">object</span> <span class="n">mode</span>
+</pre></div>
+</div>
+<table border="1" class="docutils">
+<colgroup>
+<col width="19%" />
+<col width="52%" />
+<col width="29%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Parameter name</th>
+<th class="head">Description</th>
+<th class="head">Example</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td>address</td>
+<td>Address of the Modelverse</td>
+<td><a class="reference external" href="http://localhost:8001">http://localhost:8001</a></td>
+</tr>
+<tr class="row-odd"><td>file</td>
+<td>File to be compiled</td>
+<td>file.alc</td>
+</tr>
+<tr class="row-even"><td>username</td>
+<td>Username to use when compiling</td>
+<td>test_user</td>
+</tr>
+<tr class="row-odd"><td>object</td>
+<td>Object name to export to</td>
+<td>object.o</td>
+</tr>
+<tr class="row-even"><td>mode</td>
+<td>Either CO (constructors) or PO (graph)</td>
+<td>PO</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="execute-model-py">
+<h2>execute_model.py<a class="headerlink" href="#execute-model-py" title="Permalink to this headline">¶</a></h2>
+<p>Compile a model and action language files together, executing the action language.
+First, all models are added, and then the action language is executed, starting at function &#8220;main&#8221;.
+Models being created are temporary, so they need to be exported before they can be accessed in the action language.</p>
+<p>Invocation:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">python</span> <span class="n">scripts</span><span class="o">/</span><span class="n">execute_model</span><span class="o">.</span><span class="n">py</span> <span class="n">address</span> <span class="n">username</span> <span class="n">file1</span> <span class="n">file2</span> <span class="o">...</span>
+</pre></div>
+</div>
+<table border="1" class="docutils">
+<colgroup>
+<col width="19%" />
+<col width="53%" />
+<col width="28%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Parameter name</th>
+<th class="head">Description</th>
+<th class="head">Example</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td>address</td>
+<td>Address of the Modelverse</td>
+<td><a class="reference external" href="http://localhost:8001">http://localhost:8001</a></td>
+</tr>
+<tr class="row-odd"><td>username</td>
+<td>Username to use when compiling</td>
+<td>test</td>
+</tr>
+<tr class="row-even"><td>file</td>
+<td>File to compile (either .mvc or .alc)</td>
+<td>test.alc</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="fix-files-py">
+<h2>fix_files.py<a class="headerlink" href="#fix-files-py" title="Permalink to this headline">¶</a></h2>
+<p>Fix some files that must be kept identical.
+This is sometimes necessary because if a file gets updated, the changes must propagate.
+Usually, this is done with symbolic links or similar, but there does not seem to be a nice cross-platform way of doing this in Git.</p>
+<p>Invocation:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">python</span> <span class="n">scripts</span><span class="o">/</span><span class="n">fix_files</span><span class="o">.</span><span class="n">py</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="flush-compiler-caches-py">
+<h2>flush_compiler_caches.py<a class="headerlink" href="#flush-compiler-caches-py" title="Permalink to this headline">¶</a></h2>
+<p>Clear all cached files from the compiler.
+The compiler will automatically reparse files when they have been changed, but changes to the compiler code itself will not be detected.
+When changing the compiler, this file should be executed to flush these file caches.</p>
+<p>Invocation:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">python</span> <span class="n">scripts</span><span class="o">/</span><span class="n">flush_compiler_caches</span><span class="o">.</span><span class="n">py</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="generate-bootstrap-py">
+<h2>generate_bootstrap.py<a class="headerlink" href="#generate-bootstrap-py" title="Permalink to this headline">¶</a></h2>
+<p>Creates the bootstrap file for the Modelverse State.
+This creates the necessary initial graph which contains links to all primitive code that is executed by the Modelverse before users can communicate with it.
+Generally, this needs to be executed when any file in the <em>bootstrap/</em> folder is modified.
+Compilation is fairly smart, only recompiling parts that have changed.</p>
+<p>Invocation:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">python</span> <span class="n">scripts</span><span class="o">/</span><span class="n">generate_bootstrap</span><span class="o">.</span><span class="n">py</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="link-and-load-py">
+<h2>link_and_load.py<a class="headerlink" href="#link-and-load-py" title="Permalink to this headline">¶</a></h2>
+<p>This takes a set of objects in the Modelverse, links them together in a single &#8220;executable&#8221; and executes it immediately.
+Generally not needed by end-users.</p>
+<p>Invocation:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">python</span> <span class="n">scripts</span><span class="o">/</span><span class="n">link_and_load</span><span class="o">.</span><span class="n">py</span> <span class="n">address</span> <span class="n">username</span> <span class="n">object1</span> <span class="n">object2</span> <span class="o">...</span>
+</pre></div>
+</div>
+<table border="1" class="docutils">
+<colgroup>
+<col width="19%" />
+<col width="53%" />
+<col width="28%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Parameter name</th>
+<th class="head">Description</th>
+<th class="head">Example</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td>address</td>
+<td>Address of the Modelverse</td>
+<td><a class="reference external" href="http://localhost:8001">http://localhost:8001</a></td>
+</tr>
+<tr class="row-odd"><td>username</td>
+<td>Username to use when compiling</td>
+<td>test</td>
+</tr>
+<tr class="row-even"><td>object</td>
+<td>File to compile (either .mvc or .alc)</td>
+<td>test.alc</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="make-all-py">
+<h2>make_all.py<a class="headerlink" href="#make-all-py" title="Permalink to this headline">¶</a></h2>
+<p>Compile a set of files and executes them immediately.
+This uses constructors by default, which is the most elegant, but also the slowest.</p>
+<p>Invocation:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">python</span> <span class="n">scripts</span><span class="o">/</span><span class="n">make_all</span><span class="o">.</span><span class="n">py</span> <span class="n">address</span> <span class="n">username</span> <span class="n">file1</span> <span class="n">file2</span> <span class="o">...</span>
+</pre></div>
+</div>
+<table border="1" class="docutils">
+<colgroup>
+<col width="19%" />
+<col width="53%" />
+<col width="28%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Parameter name</th>
+<th class="head">Description</th>
+<th class="head">Example</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td>address</td>
+<td>Address of the Modelverse</td>
+<td><a class="reference external" href="http://localhost:8001">http://localhost:8001</a></td>
+</tr>
+<tr class="row-odd"><td>username</td>
+<td>Username to use when compiling</td>
+<td>test</td>
+</tr>
+<tr class="row-even"><td>file</td>
+<td>File to compile (either .mvc or .alc)</td>
+<td>test.alc</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="make-parallel-py">
+<h2>make_parallel.py<a class="headerlink" href="#make-parallel-py" title="Permalink to this headline">¶</a></h2>
+<p>A parallel version of make_all.py.
+This uses the direct graph compilation, and compiles these graphs in parallel.
+This is much faster than make_all, though much less elegant.</p>
+<p>Invocation:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">python</span> <span class="n">scripts</span><span class="o">/</span><span class="n">make_parallel</span><span class="o">.</span><span class="n">py</span> <span class="n">address</span> <span class="n">username</span> <span class="n">file1</span> <span class="n">file2</span> <span class="o">...</span>
+</pre></div>
+</div>
+<table border="1" class="docutils">
+<colgroup>
+<col width="19%" />
+<col width="53%" />
+<col width="28%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Parameter name</th>
+<th class="head">Description</th>
+<th class="head">Example</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td>address</td>
+<td>Address of the Modelverse</td>
+<td><a class="reference external" href="http://localhost:8001">http://localhost:8001</a></td>
+</tr>
+<tr class="row-odd"><td>username</td>
+<td>Username to use when compiling</td>
+<td>test</td>
+</tr>
+<tr class="row-even"><td>file</td>
+<td>File to compile (either .mvc or .alc)</td>
+<td>test.alc</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="prompt-py">
+<h2>prompt.py<a class="headerlink" href="#prompt-py" title="Permalink to this headline">¶</a></h2>
+<p>A generic prompt interface to the Modelverse.
+You can log in as a specific user and start sending input messages to the Modelverse as that user.
+All output sent by the Modelverse will be printed in the console.
+There is no logic in the prompt itself, making it completely generic.</p>
+<p>Invocation:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">python</span> <span class="n">scripts</span><span class="o">/</span><span class="n">prompt</span><span class="o">.</span><span class="n">py</span>
+</pre></div>
+</div>
+</div>
+<div class="section" id="run-local-modelverse-py">
+<h2>run_local_modelverse.py<a class="headerlink" href="#run-local-modelverse-py" title="Permalink to this headline">¶</a></h2>
+<p>Locally runs an instance of the Modelverse at the requested port.
+This combines MvK and MvS at the same system, and actually makes a direct link between them, omitting the slow use of sockets.
+While this is kind of a hack at the moment, it is really necessary with the current low performance.
+To split them up, there just needs to be a statechart in between both of them (which is already written and working).</p>
+<p>Invocation:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">python</span> <span class="n">scripts</span><span class="o">/</span><span class="n">run_local_modelverse</span><span class="o">.</span><span class="n">py</span> <span class="n">port</span>
+</pre></div>
+</div>
+<table border="1" class="docutils">
+<colgroup>
+<col width="27%" />
+<col width="59%" />
+<col width="14%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Parameter name</th>
+<th class="head">Description</th>
+<th class="head">Example</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td>port</td>
+<td>Port to host the Modelverse on</td>
+<td>8001</td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="section" id="run-tests-py">
+<h2>run_tests.py<a class="headerlink" href="#run-tests-py" title="Permalink to this headline">¶</a></h2>
+<p>Run the tests for all parts of the Modelverse.</p>
+<p>Invocation:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">python</span> <span class="n">scripts</span><span class="o">/</span><span class="n">run_tests</span><span class="o">.</span><span class="n">py</span>
+</pre></div>
+</div>
+</div>
+</div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
+        <div class="sphinxsidebarwrapper">
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">How to run</a><ul>
+<li><a class="reference internal" href="#check-objects-py">check_objects.py</a></li>
+<li><a class="reference internal" href="#compile-py">compile.py</a></li>
+<li><a class="reference internal" href="#execute-model-py">execute_model.py</a></li>
+<li><a class="reference internal" href="#fix-files-py">fix_files.py</a></li>
+<li><a class="reference internal" href="#flush-compiler-caches-py">flush_compiler_caches.py</a></li>
+<li><a class="reference internal" href="#generate-bootstrap-py">generate_bootstrap.py</a></li>
+<li><a class="reference internal" href="#link-and-load-py">link_and_load.py</a></li>
+<li><a class="reference internal" href="#make-all-py">make_all.py</a></li>
+<li><a class="reference internal" href="#make-parallel-py">make_parallel.py</a></li>
+<li><a class="reference internal" href="#prompt-py">prompt.py</a></li>
+<li><a class="reference internal" href="#run-local-modelverse-py">run_local_modelverse.py</a></li>
+<li><a class="reference internal" href="#run-tests-py">run_tests.py</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="components.html"
+                        title="previous chapter">Modelverse components</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="actionlanguage.html"
+                        title="next chapter">Action Language</a></p>
+  <div role="note" aria-label="source link">
+    <h3>This Page</h3>
+    <ul class="this-page-menu">
+      <li><a href="_sources/howto.txt"
+            rel="nofollow">Show Source</a></li>
+    </ul>
+   </div>
+<div id="searchbox" style="display: none" role="search">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <div><input type="text" name="q" /></div>
+      <div><input type="submit" value="Go" /></div>
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="actionlanguage.html" title="Action Language"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="components.html" title="Modelverse components"
+             >previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>
+    <div class="footer" role="contentinfo">
+        &#169; Copyright 2016, Yentl Van Tendeloo.
+      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.6.
+    </div>
+  </body>
+</html>

+ 175 - 0
doc/_build/html/index.html

@@ -0,0 +1,175 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Welcome to Modelverse’s documentation! &#8212; Modelverse 0.4.0 documentation</title>
+    
+    <link rel="stylesheet" href="_static/classic.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    './',
+        VERSION:     '0.4.0',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="Modelverse 0.4.0 documentation" href="#" />
+    <link rel="next" title="Installation" href="installation.html" /> 
+  </head>
+  <body role="document">
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="installation.html" title="Installation"
+             accesskey="N">next</a> |</li>
+        <li class="nav-item nav-item-0"><a href="#">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body" role="main">
+            
+  <div class="section" id="welcome-to-modelverse-s-documentation">
+<h1>Welcome to Modelverse&#8217;s documentation!<a class="headerlink" href="#welcome-to-modelverse-s-documentation" title="Permalink to this headline">¶</a></h1>
+<p>Contents:</p>
+<div class="toctree-wrapper compound">
+<ul>
+<li class="toctree-l1"><a class="reference internal" href="installation.html">Installation</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="installation.html#dependencies">Dependencies</a></li>
+<li class="toctree-l2"><a class="reference internal" href="installation.html#id1">Installation</a></li>
+<li class="toctree-l2"><a class="reference internal" href="installation.html#tests">Tests</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="components.html">Modelverse components</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="components.html#modelverse-state-mvs">Modelverse State (MvS)</a></li>
+<li class="toctree-l2"><a class="reference internal" href="components.html#modelverse-kernel-mvk">Modelverse Kernel (MvK)</a></li>
+<li class="toctree-l2"><a class="reference internal" href="components.html#modelverse-interface-mvi">Modelverse Interface (MvI)</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="howto.html">How to run</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="howto.html#check-objects-py">check_objects.py</a></li>
+<li class="toctree-l2"><a class="reference internal" href="howto.html#compile-py">compile.py</a></li>
+<li class="toctree-l2"><a class="reference internal" href="howto.html#execute-model-py">execute_model.py</a></li>
+<li class="toctree-l2"><a class="reference internal" href="howto.html#fix-files-py">fix_files.py</a></li>
+<li class="toctree-l2"><a class="reference internal" href="howto.html#flush-compiler-caches-py">flush_compiler_caches.py</a></li>
+<li class="toctree-l2"><a class="reference internal" href="howto.html#generate-bootstrap-py">generate_bootstrap.py</a></li>
+<li class="toctree-l2"><a class="reference internal" href="howto.html#link-and-load-py">link_and_load.py</a></li>
+<li class="toctree-l2"><a class="reference internal" href="howto.html#make-all-py">make_all.py</a></li>
+<li class="toctree-l2"><a class="reference internal" href="howto.html#make-parallel-py">make_parallel.py</a></li>
+<li class="toctree-l2"><a class="reference internal" href="howto.html#prompt-py">prompt.py</a></li>
+<li class="toctree-l2"><a class="reference internal" href="howto.html#run-local-modelverse-py">run_local_modelverse.py</a></li>
+<li class="toctree-l2"><a class="reference internal" href="howto.html#run-tests-py">run_tests.py</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="actionlanguage.html">Action Language</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="actionlanguage.html#files">Files</a></li>
+<li class="toctree-l2"><a class="reference internal" href="actionlanguage.html#language-description">Language description</a></li>
+<li class="toctree-l2"><a class="reference internal" href="actionlanguage.html#examples">Examples</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="modellanguage.html">Modelling Language</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="modellanguage.html#language-description">Language description</a></li>
+<li class="toctree-l2"><a class="reference internal" href="modellanguage.html#merge-with-action-language">Merge with Action Language</a></li>
+<li class="toctree-l2"><a class="reference internal" href="modellanguage.html#examples">Examples</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="examples.html">Examples</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="examples.html#fibonacci-server">Fibonacci Server</a></li>
+<li class="toctree-l2"><a class="reference internal" href="examples.html#modelling-server">Modelling Server</a></li>
+<li class="toctree-l2"><a class="reference internal" href="examples.html#upload-model">Upload model</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="advanced.html">Advanced examples</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="advanced.html#inheritance-semantics">Inheritance Semantics</a></li>
+<li class="toctree-l2"><a class="reference internal" href="advanced.html#instantiation-semantics">Instantiation Semantics</a></li>
+<li class="toctree-l2"><a class="reference internal" href="advanced.html#conformance-semantics">Conformance Semantics</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="problems.html">Common problems and solutions</a></li>
+<li class="toctree-l1"><a class="reference internal" href="internal.html">Internal workings</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="internal.html#modelverse-state">Modelverse State</a></li>
+<li class="toctree-l2"><a class="reference internal" href="internal.html#modelverse-kernel">Modelverse Kernel</a></li>
+<li class="toctree-l2"><a class="reference internal" href="internal.html#modelverse-interface">Modelverse Interface</a></li>
+<li class="toctree-l2"><a class="reference internal" href="internal.html#bootstrapping">Bootstrapping</a></li>
+<li class="toctree-l2"><a class="reference internal" href="internal.html#how-to-add-a-primitive">How to add a primitive</a></li>
+<li class="toctree-l2"><a class="reference internal" href="internal.html#adding-a-precompiled-function">Adding a precompiled function</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="interface.html">Interface</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="interface.html#mvs-server">MvS server</a></li>
+<li class="toctree-l2"><a class="reference internal" href="interface.html#mvk-server">MvK server</a></li>
+</ul>
+</li>
+<li class="toctree-l1"><a class="reference internal" href="communication_models.html">Network communication models</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="communication_models.html#mvs-server">MvS server</a></li>
+<li class="toctree-l2"><a class="reference internal" href="communication_models.html#mvk-server">MvK server</a></li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
+        <div class="sphinxsidebarwrapper">
+  <h4>Next topic</h4>
+  <p class="topless"><a href="installation.html"
+                        title="next chapter">Installation</a></p>
+  <div role="note" aria-label="source link">
+    <h3>This Page</h3>
+    <ul class="this-page-menu">
+      <li><a href="_sources/index.txt"
+            rel="nofollow">Show Source</a></li>
+    </ul>
+   </div>
+<div id="searchbox" style="display: none" role="search">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <div><input type="text" name="q" /></div>
+      <div><input type="submit" value="Go" /></div>
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="installation.html" title="Installation"
+             >next</a> |</li>
+        <li class="nav-item nav-item-0"><a href="#">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>
+    <div class="footer" role="contentinfo">
+        &#169; Copyright 2016, Yentl Van Tendeloo.
+      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.6.
+    </div>
+  </body>
+</html>

Разница между файлами не показана из-за своего большого размера
+ 189 - 0
doc/_build/html/installation.html


+ 267 - 0
doc/_build/html/interface.html

@@ -0,0 +1,267 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Interface description &#8212; Modelverse 0.4.0 documentation</title>
+    
+    <link rel="stylesheet" href="_static/classic.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    './',
+        VERSION:     '0.4.0',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="Modelverse 0.4.0 documentation" href="index.html" />
+    <link rel="next" title="Communication models" href="communication_models.html" />
+    <link rel="prev" title="Internal workings" href="internal.html" /> 
+  </head>
+  <body role="document">
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="communication_models.html" title="Communication models"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="internal.html" title="Internal workings"
+             accesskey="P">previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body" role="main">
+            
+  <div class="section" id="interface-description">
+<h1>Interface description<a class="headerlink" href="#interface-description" title="Permalink to this headline">¶</a></h1>
+<p>All Modelverse components communicate with each other through the use of sockets.
+On these sockets, XML/HTTP Requests are used for communication.
+In this brief section, we describe the form of these requests.</p>
+<div class="section" id="mvs-server">
+<h2>MvS server<a class="headerlink" href="#mvs-server" title="Permalink to this headline">¶</a></h2>
+<p>The MvS server listens to a fixed set of commands.
+All commands have a fully defined signature and result.
+Note that commands are encoded: a decoding table is presented below.</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="15%" />
+<col width="85%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Code</th>
+<th class="head">Description</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td>CN</td>
+<td>create_node</td>
+</tr>
+<tr class="row-odd"><td>CE</td>
+<td>create_edge</td>
+</tr>
+<tr class="row-even"><td>CNV</td>
+<td>create_nodevalue</td>
+</tr>
+<tr class="row-odd"><td>CD</td>
+<td>create_dict</td>
+</tr>
+<tr class="row-even"><td>RV</td>
+<td>read_value</td>
+</tr>
+<tr class="row-odd"><td>RO</td>
+<td>read_outgoing</td>
+</tr>
+<tr class="row-even"><td>RI</td>
+<td>read_incoming</td>
+</tr>
+<tr class="row-odd"><td>RE</td>
+<td>read_edge</td>
+</tr>
+<tr class="row-even"><td>RD</td>
+<td>read_dict</td>
+</tr>
+<tr class="row-odd"><td>RDN</td>
+<td>read_dict_node</td>
+</tr>
+<tr class="row-even"><td>RDNE</td>
+<td>read_dict_node_edge</td>
+</tr>
+<tr class="row-odd"><td>RDE</td>
+<td>read_dict_edge</td>
+</tr>
+<tr class="row-even"><td>RRD</td>
+<td>read_reverse_dict</td>
+</tr>
+<tr class="row-odd"><td>RR</td>
+<td>read_root</td>
+</tr>
+<tr class="row-even"><td>RDK</td>
+<td>read_dict_keys</td>
+</tr>
+<tr class="row-odd"><td>DE</td>
+<td>delete_edge</td>
+</tr>
+<tr class="row-even"><td>DN</td>
+<td>delete_node</td>
+</tr>
+</tbody>
+</table>
+<p>Requests are sent as POST requests (<em>i.e.</em>, in the data of a HTTP request).
+They have the following form:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">op</span><span class="o">=</span><span class="n">CODE</span><span class="o">&amp;</span><span class="n">params</span><span class="o">=</span><span class="n">PARAMS</span>
+</pre></div>
+</div>
+<p>In this case, <em>CODE</em> is one of the codes mentioned above, and the value of <em>PARAMS</em> is a JSON encoded list of Modelverse identifiers.
+The choice of what is a Modelverse identifier is left to the MvS itself.</p>
+<p>The result will be a JSON serialized list containing as first element the response to the request, and as second element the statuscode.
+If the statuscode is 200, the first element will be correct.
+Otherwise, the statuscode indicates the error, and the first element is set to <em>null</em>.</p>
+</div>
+<div class="section" id="mvk-server">
+<h2>MvK server<a class="headerlink" href="#mvk-server" title="Permalink to this headline">¶</a></h2>
+<p>The communication with the MvK is a lot easier, as there is only a very minimal interface: the actual interface needs to be explicitly modelled in action language.
+Requests have the following form:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">op</span><span class="o">=</span><span class="n">OPERATION</span><span class="o">&amp;</span><span class="n">username</span><span class="o">=</span><span class="n">USERNAME</span><span class="o">&amp;</span><span class="n">value</span><span class="o">=</span><span class="n">VALUE</span>
+</pre></div>
+</div>
+<p>Here, <em>OPERATION</em> defines the operation to execute, of which only two exist:</p>
+<ol class="arabic simple">
+<li><em>set_input</em>, which adds the sent value to the input queue of the user;</li>
+<li><em>get_output</em>, which blocks until there is a value in the output queue of the user.</li>
+</ol>
+<p>Obviously, <em>USERNAME</em> specifies the name of the user for which the operation needs to happen.</p>
+<p>The <em>VALUE</em> is just a JSON encoded value which will be added to the input queue of the Modelverse.
+This is ignored when the <em>get_output</em> operation is used.
+Note that there are some minor differences between our encoding and JSON encoding.</p>
+<p>The supported types are shown below.</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="27%" />
+<col width="73%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Type</th>
+<th class="head">Example</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td>Integer</td>
+<td>1</td>
+</tr>
+<tr class="row-odd"><td>Float</td>
+<td>1.0</td>
+</tr>
+<tr class="row-even"><td>Boolean</td>
+<td>true</td>
+</tr>
+<tr class="row-odd"><td>String</td>
+<td>&#8220;abc&#8221;</td>
+</tr>
+<tr class="row-even"><td>Action</td>
+<td>if</td>
+</tr>
+</tbody>
+</table>
+<p>While this list mostly resembles JSON, there are some important differences:</p>
+<ul class="simple">
+<li>Lists and objects are not supported;</li>
+<li>Null object is not supported;</li>
+<li>Action type is new, and contains a string representation (without quotes!) of the action language construct to add</li>
+</ul>
+<p>As response, the <em>set_input</em> will always receive the same reply if the message was correctly deserialized.
+Receiving a reply does <em>NOT</em> mean that a message was consumed by the user, it only means that the message was correctly added to the input queue of that user.</p>
+<p>A <em>get_output</em> request blocks until a value is available in the users output queue.
+The reply to this message will then contain a JSON serialized (with identical remarks as for <em>set_input</em>) containing the value that was output.
+Note that now the <em>null</em> message is possible, in case the node that is being outputted does not contain a value (or is an edge).</p>
+<div class="section" id="performance-notes">
+<h3>Performance notes<a class="headerlink" href="#performance-notes" title="Permalink to this headline">¶</a></h3>
+<p>For performance reasons, sending a huge amount of data to the Modelverse (<em>e.g.</em>, a compiled program), should not happen with individual requests for each line.
+To allow for packed messages, users can ignore the <em>value</em> parameter, and use the <em>data</em> parameter instead.
+The content of this parameter should be a JSON encoded list of all individual values to be inserted.</p>
+</div>
+</div>
+</div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
+        <div class="sphinxsidebarwrapper">
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Interface description</a><ul>
+<li><a class="reference internal" href="#mvs-server">MvS server</a></li>
+<li><a class="reference internal" href="#mvk-server">MvK server</a><ul>
+<li><a class="reference internal" href="#performance-notes">Performance notes</a></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="internal.html"
+                        title="previous chapter">Internal workings</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="communication_models.html"
+                        title="next chapter">Communication models</a></p>
+  <div role="note" aria-label="source link">
+    <h3>This Page</h3>
+    <ul class="this-page-menu">
+      <li><a href="_sources/interface.txt"
+            rel="nofollow">Show Source</a></li>
+    </ul>
+   </div>
+<div id="searchbox" style="display: none" role="search">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <div><input type="text" name="q" /></div>
+      <div><input type="submit" value="Go" /></div>
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="communication_models.html" title="Communication models"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="internal.html" title="Internal workings"
+             >previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>
+    <div class="footer" role="contentinfo">
+        &#169; Copyright 2016, Yentl Van Tendeloo.
+      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.6.
+    </div>
+  </body>
+</html>

+ 364 - 0
doc/_build/html/internal.html

@@ -0,0 +1,364 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Internal workings &#8212; Modelverse 0.4.0 documentation</title>
+    
+    <link rel="stylesheet" href="_static/classic.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    './',
+        VERSION:     '0.4.0',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="Modelverse 0.4.0 documentation" href="index.html" />
+    <link rel="next" title="Interface description" href="interface.html" />
+    <link rel="prev" title="Common problems and solutions" href="problems.html" /> 
+  </head>
+  <body role="document">
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="interface.html" title="Interface description"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="problems.html" title="Common problems and solutions"
+             accesskey="P">previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body" role="main">
+            
+  <div class="section" id="internal-workings">
+<h1>Internal workings<a class="headerlink" href="#internal-workings" title="Permalink to this headline">¶</a></h1>
+<p>For more detailed information on the Modelverse specification, which this project is implementing, we refer to the <a class="reference external" href="http://msdl.cs.mcgill.ca/people/yentl/files/Modelverse.pdf">Modelverse Specification</a>.</p>
+<p>Information on the implementation can be found below.</p>
+<div class="section" id="modelverse-state">
+<h2>Modelverse State<a class="headerlink" href="#modelverse-state" title="Permalink to this headline">¶</a></h2>
+<p>The Modelverse State is basically just an implementation of a graph library.
+As we have a particular kind of graph, this implementation is mostly done by hand at the moment.
+The notable exception to this is the RDF backend, proving that other implementations can also be used.</p>
+<p>The basic implementation just stores everything as dictionaries.
+All operations are then defined by doing operations on these dictionaries.
+The most interesting operations here are dictionary operations, which need to traverse these dictionaries in complex ways.
+To overcome performance problems for these operations, all results are cached (and validated afterwards).</p>
+<div class="section" id="rdf-backend">
+<h3>RDF backend<a class="headerlink" href="#rdf-backend" title="Permalink to this headline">¶</a></h3>
+<p>The RDF backend requires the <em>rdflib</em> module in Python.
+The Modelverse graph is then stored in RDF representation and all operations on it are done using SPARQL queries.
+Due to this level of indirection, performance is extremely slow.
+To increase performance, we would likely have to make more <em>composite</em> operations, or even group different requests together internally.</p>
+</div>
+<div class="section" id="status-codes">
+<h3>Status codes<a class="headerlink" href="#status-codes" title="Permalink to this headline">¶</a></h3>
+<p>The MvS returns, apart from its actual return value, a status code for the request.
+This value is not used by the MvK at all, since sometimes a request is expected to give an error (<em>e.g.</em>, checking whether an element is present).
+When debugging the MvS, however, these status codes can come in handy.</p>
+</div>
+</div>
+<div class="section" id="modelverse-kernel">
+<h2>Modelverse Kernel<a class="headerlink" href="#modelverse-kernel" title="Permalink to this headline">¶</a></h2>
+<p>The Modelverse Kernel is basically a graph transformation kernel.
+It consists of two parts: a small transformation engine (only a few lines in Python), and a copy of all rules it knows.
+Most code is an encoding of these transformation rules, and can (theoretically) be automatically generated by the Modelverse itself.
+This is currently not top priority, but will probably be implemented in the future.</p>
+<p>The transformation rules are an encoding of the rules presented in the specification mentioned at the top of this page.
+In each rule, the MvK needs to have tight communication with the MvS.
+For this, the rules are encoded using <em>yield</em> operations in Python.
+Rules therefore act as generators, outputting commands to the MvS, and immediately getting a reply.
+Each individual yield contains a list of operations to send to the MvS simultaneously.
+The result will therefore also be a list of results for each operation.</p>
+<p>As you can see in these rules, each entry in the list has a specific form.
+An entry is a tuple containing two elements: the code of the operation to execute, followed by a list of all parameters to pass.
+The code is a shortened name for the operation, such as <em>CN</em> for <em>create_node</em>.
+A full mapping can be found in the MvS, the most important ones are shown below.</p>
+<table border="1" class="docutils">
+<colgroup>
+<col width="20%" />
+<col width="80%" />
+</colgroup>
+<thead valign="bottom">
+<tr class="row-odd"><th class="head">Code</th>
+<th class="head">Function</th>
+</tr>
+</thead>
+<tbody valign="top">
+<tr class="row-even"><td>CN</td>
+<td>create_node</td>
+</tr>
+<tr class="row-odd"><td>CNV</td>
+<td>create_nodevalue</td>
+</tr>
+<tr class="row-even"><td>CE</td>
+<td>create_edge</td>
+</tr>
+<tr class="row-odd"><td>CD</td>
+<td>create_dict</td>
+</tr>
+<tr class="row-even"><td>RV</td>
+<td>read_value</td>
+</tr>
+<tr class="row-odd"><td>RE</td>
+<td>read_edge</td>
+</tr>
+<tr class="row-even"><td>RD</td>
+<td>read_dict</td>
+</tr>
+<tr class="row-odd"><td>RDN</td>
+<td>read_dict_node</td>
+</tr>
+<tr class="row-even"><td>DN</td>
+<td>delete_node</td>
+</tr>
+<tr class="row-odd"><td>DE</td>
+<td>delete_edge</td>
+</tr>
+</tbody>
+</table>
+<div class="admonition note">
+<p class="first admonition-title">Note</p>
+<p>Since each yield operation works on lists even a single operation needs to be wrapped in a list.
+Worse, however, is that the return value will also be a list.
+Instead of having to take the first element each time, Python allows you to write a comma after the variable, to make it expand it automatically.
+Your syntax thus becomes:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">a</span><span class="p">,</span> <span class="o">=</span> <span class="k">yield</span> <span class="p">[(</span><span class="s">&quot;CN&quot;</span><span class="p">,</span> <span class="p">[])]</span>
+</pre></div>
+</div>
+<p class="last">Where a will now already contain the created node, and not a list with as first (and only) element the created node.</p>
+</div>
+<div class="section" id="primitives">
+<h3>Primitives<a class="headerlink" href="#primitives" title="Permalink to this headline">¶</a></h3>
+<p>The Modelverse Kernel also defines the primitives users can use.
+Primitives are necessary since we can&#8217;t go deeper at some point.
+It is the MvK&#8217;s responsibility to implement each and every primitive defined in the bootstrap file.</p>
+<p>Primitives are implemented in the bootstrap file as having a body with an empty node.
+When execution goes to this node, the MvK must execute the associated primitive instead.
+To do this, the MvK must map all these nodes to their corresponding primitive implementation during startup.</p>
+</div>
+<div class="section" id="precompiled-functions">
+<h3>Precompiled functions<a class="headerlink" href="#precompiled-functions" title="Permalink to this headline">¶</a></h3>
+<p>Similar to primitives, the MvK also supports precompiled functions.
+A precompiled function is similar to a primitive in terms of implementation, but they do also have an implementation inside of the Modelverse itself.
+This means that there are two implementations: one hardcoded, and one in action language.
+Both should obviously be consistent.</p>
+<p>Whereas primitives are required for a functional Modelverse, precompiled functions are only a performance optimization, and can be disabled by the user for debugging purposes.
+This is interesting, since with precompiled functions, no intermediate values will be visible.
+Additionally, precompiled functions cannot be changed, as they are Python code instead of being explicitly modelled.</p>
+</div>
+</div>
+<div class="section" id="modelverse-interface">
+<h2>Modelverse Interface<a class="headerlink" href="#modelverse-interface" title="Permalink to this headline">¶</a></h2>
+<p>Finally, we come to the Modelverse Interface.
+For the moment, this is only a simple compiler that takes action language or model language files and translates them to something the Modelverse can understand.
+There are basically two kinds of operations the Modelverse can understand: direct graphs, or a list of constructors.
+The use of direct graphs is deprecated, as constructors are much more elegant (but slower).
+Future changes should make constructors as fast as the use of graphs.
+Nonetheless, which approach is used does not matter for the action language or model language files.</p>
+<p>The parser used for this simple front-end is the HUTN parser.
+It creates an abstract syntax tree, which is then traversed by a series of visitors.
+The visitors that are used, depends on the selected mode of compilation.
+We briefly present the most important visitors.</p>
+<div class="section" id="semantics-visitor">
+<h3>Semantics visitor<a class="headerlink" href="#semantics-visitor" title="Permalink to this headline">¶</a></h3>
+<p>The visitor most oftenly used is the Semantics visitor.
+It traverses the abstract syntax tree and constructs symbol tables and finds all declarations of functions.
+Additionally, it also translates the use of operators to their Modelverse functions.</p>
+<p>This visitor in itself does not output anything, but it modifies the existing abstract syntax tree.
+It is used as a first step for most other visitors.</p>
+</div>
+<div class="section" id="constructors-visitor">
+<h3>Constructors visitor<a class="headerlink" href="#constructors-visitor" title="Permalink to this headline">¶</a></h3>
+<p>The most important visitor is the constructors visitor.
+It traverses the abstract syntax tree and outputs a list of strings that make it possible for the MvK to construct the required code in the Modelverse.
+The use of constructors has several advantages, but the primary advantage is that the interface does not have to know about the internal representation of action language in the Modelverse.
+However, the order of constructors and accepted keywords needs to be defined (in action language), and made available to the users.
+As this interface is explicitly modelled as well, it is possible for users to modify it without affecting the interface.
+This is bad if the interface suddenly accepts new keywords or removes support for old keywords.</p>
+<p>During the execution of the visitor, it would already be possible to start transmitting the list to the Modelverse, such that the Modelverse can create the code in parallel with the actual parsing.
+While this is possible, we currently split this up in different phases: first the list is generated completely, and then it is transferred to the Modelverse in a single request.</p>
+</div>
+<div class="section" id="primitives-visitor">
+<h3>Primitives visitor<a class="headerlink" href="#primitives-visitor" title="Permalink to this headline">¶</a></h3>
+<p>The primitives visitor generates a Modelverse graph directly.
+Its use is deprecated, as the constructors are much more elegant.
+While direct use of this visitor is not recommended, except for performance reasons, the bootstrap visitor (discussed next) is based on this visitor.</p>
+<p>This visitor creates a serialized version of the graph and transmits it to the Modelverse.
+The Modelverse has a built-in primitive to decode this graph and store it.</p>
+</div>
+<div class="section" id="bootstrap-visitor">
+<h3>Bootstrap visitor<a class="headerlink" href="#bootstrap-visitor" title="Permalink to this headline">¶</a></h3>
+<p>Despite the primitives visitor being deprecated, the bootstrap visitor still needs access to this kind of output, since it cannot use constructors: during bootstrapping, the Modelverse is not yet available.
+The actual output format slightly differs from the primitives visitor, but the core concepts are identical.</p>
+</div>
+<div class="section" id="model-visitor">
+<h3>Model visitor<a class="headerlink" href="#model-visitor" title="Permalink to this headline">¶</a></h3>
+<p>Finally, the model visitor is similar to the constructor visitor, but goes to a different constructor interface, which supports modelling operations instead of action language operations.
+This is a very preliminary visitor.</p>
+</div>
+</div>
+<div class="section" id="bootstrapping">
+<h2>Bootstrapping<a class="headerlink" href="#bootstrapping" title="Permalink to this headline">¶</a></h2>
+<p>To bootstrap, you just have to run the file <em>bootstrap.py</em>.
+Here, we explain what this file actually does...</p>
+<p>The bootstrap script primarily creates the initial graph manually.
+This manual creation is done by writing data to a file, which is later read by the MvS.
+The initial graph consists of several parts:</p>
+<ul class="simple">
+<li>The Modelverse Root node;</li>
+<li>A global definition of all primitives;</li>
+<li>The stack frame of the initial user <em>user_manager</em>, which manages all other users;</li>
+<li>The code for the <em>user_manager</em> user;</li>
+<li>The code for all new users, as assigned by the <em>user_manager</em>;</li>
+<li>Bindings in the compilation manager for bootstrap files.</li>
+</ul>
+<p>These are all fairly simple in themselves.
+For some parts, such as the code, the HUTN compiler is invoked on a temporary piece of code.
+All bootstrap files are also compiled and made available to the compilation manager with their MD5 hash.</p>
+</div>
+<div class="section" id="how-to-add-a-primitive">
+<h2>How to add a primitive<a class="headerlink" href="#how-to-add-a-primitive" title="Permalink to this headline">¶</a></h2>
+<p>Probably the most important reason why you would want to know about the Modelverse internals, is if you want to add a Modelverse primitive.
+Primitives are functions implemented in the MvK core, and thus become hardcoded.</p>
+<div class="admonition warning">
+<p class="first admonition-title">Warning</p>
+<p class="last">While these functions are hardcoded, their implementation needs to follow strict rules, such that their semantics is identical in all possible programming languages.
+For example, a primitive <em>getTime()</em> cannot simply be implemented as <em>time.time()</em> in Python, as this gives different results on Linux and Windows.</p>
+</div>
+<p>To add a primitive, follow these steps:</p>
+<ol class="arabic">
+<li><p class="first">Add the code of the primitive to the MvK implementation by adding it in the file <em>primitives.py</em>.</p>
+<blockquote>
+<div><ol class="loweralpha simple">
+<li>Name the function identically to how the primitive will be invoked later on.</li>
+<li>Take a set of parameters. Parameters for primitives are always positional and start from <em>a</em> onwards.</li>
+<li>The final parameter should be a catch-all element, as it is possible that a high number of additional information is passed. In Python, this is done with a parameter prepended with **.</li>
+<li>When asking the MvS for information, use yields, just like the implementation of transformation rules in the MvK.</li>
+<li>Instead of return, use a <em>raise</em> with the exception <em>PrimitiveFinished</em>. This exception takes one argument: the returnvalue.</li>
+</ol>
+</div></blockquote>
+</li>
+<li><p class="first">Add the signature to <em>bootstrap.py</em> in the topmost dictionary <em>primitives</em>. The key is the name of the function, and the value is a list starting with the return type, followed by all parameter types (as string).</p>
+</li>
+<li><p class="first">Add the declaration to <em>includes/primitives.alh</em> to make them available everywhere.</p>
+</li>
+<li><p class="first">Add the definition to <em>primitives.alc</em> and assign the Modelverse reference <em>?primitives/function_name</em>.</p>
+</li>
+<li><p class="first">Recreate the bootstrap file by running the script <em>generate_bootstrap.py</em>.</p>
+</li>
+<li><p class="first">Restart the Modelverse to reload the bootstrap file.</p>
+</li>
+<li><p class="first">From now on, all files including <em>primitives.alh</em> have access to the defined function.</p>
+</li>
+</ol>
+</div>
+<div class="section" id="adding-a-precompiled-function">
+<h2>Adding a precompiled function<a class="headerlink" href="#adding-a-precompiled-function" title="Permalink to this headline">¶</a></h2>
+<p>Adding a precompiled function is way easier: only step 1 of the addition of a primitive should be done, but in the file <em>compiled.py</em> instead of <em>primitives.py</em>.
+All other steps are done automatically since there is an action language implementation present.
+The MvK will then automatically pick the precompiled function or the explicitly modelled operation, depending on preferences.
+A restart of the MvK is needed for Python to pick up the new functions.</p>
+</div>
+</div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
+        <div class="sphinxsidebarwrapper">
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Internal workings</a><ul>
+<li><a class="reference internal" href="#modelverse-state">Modelverse State</a><ul>
+<li><a class="reference internal" href="#rdf-backend">RDF backend</a></li>
+<li><a class="reference internal" href="#status-codes">Status codes</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#modelverse-kernel">Modelverse Kernel</a><ul>
+<li><a class="reference internal" href="#primitives">Primitives</a></li>
+<li><a class="reference internal" href="#precompiled-functions">Precompiled functions</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#modelverse-interface">Modelverse Interface</a><ul>
+<li><a class="reference internal" href="#semantics-visitor">Semantics visitor</a></li>
+<li><a class="reference internal" href="#constructors-visitor">Constructors visitor</a></li>
+<li><a class="reference internal" href="#primitives-visitor">Primitives visitor</a></li>
+<li><a class="reference internal" href="#bootstrap-visitor">Bootstrap visitor</a></li>
+<li><a class="reference internal" href="#model-visitor">Model visitor</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#bootstrapping">Bootstrapping</a></li>
+<li><a class="reference internal" href="#how-to-add-a-primitive">How to add a primitive</a></li>
+<li><a class="reference internal" href="#adding-a-precompiled-function">Adding a precompiled function</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="problems.html"
+                        title="previous chapter">Common problems and solutions</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="interface.html"
+                        title="next chapter">Interface description</a></p>
+  <div role="note" aria-label="source link">
+    <h3>This Page</h3>
+    <ul class="this-page-menu">
+      <li><a href="_sources/internal.txt"
+            rel="nofollow">Show Source</a></li>
+    </ul>
+   </div>
+<div id="searchbox" style="display: none" role="search">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <div><input type="text" name="q" /></div>
+      <div><input type="submit" value="Go" /></div>
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="interface.html" title="Interface description"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="problems.html" title="Common problems and solutions"
+             >previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>
+    <div class="footer" role="contentinfo">
+        &#169; Copyright 2016, Yentl Van Tendeloo.
+      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.6.
+    </div>
+  </body>
+</html>

+ 289 - 0
doc/_build/html/modellanguage.html

@@ -0,0 +1,289 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Modelling Language &#8212; Modelverse 0.4.0 documentation</title>
+    
+    <link rel="stylesheet" href="_static/classic.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    './',
+        VERSION:     '0.4.0',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="Modelverse 0.4.0 documentation" href="index.html" />
+    <link rel="next" title="Examples" href="examples.html" />
+    <link rel="prev" title="Action Language" href="actionlanguage.html" /> 
+  </head>
+  <body role="document">
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="examples.html" title="Examples"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="actionlanguage.html" title="Action Language"
+             accesskey="P">previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body" role="main">
+            
+  <div class="section" id="modelling-language">
+<h1>Modelling Language<a class="headerlink" href="#modelling-language" title="Permalink to this headline">¶</a></h1>
+<p>Apart from the action language, the Modelverse also has a modelling language.
+With this language, models (<em>i.e.</em>, data) can be defined in addition to the algorithms.</p>
+<p>This language is still mostly work in progress, but should be decent enough to construct simple metamodels and instantiate them.
+All models have the extension *.mvc, indicating that they are models and should be compiled as such.</p>
+<div class="section" id="language-description">
+<h2>Language description<a class="headerlink" href="#language-description" title="Permalink to this headline">¶</a></h2>
+<p>The modelling language defines data structures, which will be formed as models in the Modelverse.</p>
+<p>Several constructs are supported.</p>
+<div class="section" id="import">
+<h3>Import<a class="headerlink" href="#import" title="Permalink to this headline">¶</a></h3>
+<p>An import pulls in a model and makes it accessible using a simpler identifier.
+The structure is as follows:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">path</span><span class="o">/</span><span class="ow">in</span><span class="o">/</span><span class="n">modelverse</span> <span class="k">as</span> <span class="n">my_model</span>
+</pre></div>
+</div>
+<p>After this import, the model that was previously exported to <em>path/in/modelverse</em> becomes available as <em>my_model</em>.</p>
+</div>
+<div class="section" id="include">
+<h3>Include<a class="headerlink" href="#include" title="Permalink to this headline">¶</a></h3>
+<p>When combined with action language, the action language might require some includes of header files.
+To do this, the includes can be placed at the top of the hierarchy.</p>
+</div>
+<div class="section" id="model">
+<h3>Model<a class="headerlink" href="#model" title="Permalink to this headline">¶</a></h3>
+<p>Every model is defined by first specifying the type of model to instantiate, followed by the name of the model to create.
+The name of the model can then later on be referenced in other models (as type, or for exporting).
+Within the model, all names of the type model can be used as types again.</p>
+</div>
+<div class="section" id="instance">
+<h3>Instance<a class="headerlink" href="#instance" title="Permalink to this headline">¶</a></h3>
+<p>A model consists of some instances.
+These instances are instances of types specified by the model that is the metaclass of the current model.</p>
+</div>
+<div class="section" id="attribute">
+<h3>Attribute<a class="headerlink" href="#attribute" title="Permalink to this headline">¶</a></h3>
+<p>Each model instance can contain attributes.
+There are two kinds of attributes: defining attributes, or value attributes.</p>
+<p>For defining attributes, the structure is as follows:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">Class</span> <span class="n">A</span><span class="p">{</span>
+    <span class="n">my_parameter</span> <span class="p">:</span> <span class="n">ParameterType</span>
+<span class="p">}</span>
+</pre></div>
+</div>
+<p>This defines a parameter called <em>my_parameter</em> which is typed by <em>ParameterType</em>.
+<em>ParameterType</em> must always be a type defined in the type that is being instantiated.
+Even if this is a primitive, such as <em>Integer</em>, the metamodel must define what it calls an <em>Integer</em>.
+While this might seem bothersome, this clearly defines the notion of what a type means, without having to resort to the implementation.</p>
+<p>Value attributes are similar, but have a different syntax, and contain an actual value.
+Their structure is as follows:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="n">A</span> <span class="n">a</span><span class="p">{</span>
+    <span class="n">my_parameter</span> <span class="o">=</span> <span class="mi">1</span>
+<span class="p">}</span>
+</pre></div>
+</div>
+<p>They assign a value to a previously defined attribute.
+In this case, it is important that the value conforms to the type specified in the defining attribute.</p>
+</div>
+</div>
+<div class="section" id="merge-with-action-language">
+<h2>Merge with Action Language<a class="headerlink" href="#merge-with-action-language" title="Permalink to this headline">¶</a></h2>
+<p>It is of course possible to incorporate action language inside of a model.
+A typical use case for this is the definition of constraints or actions.
+Action language is surrounded by dollar signs ($), which causes the parser to redirect the text between dollar signs to the action language parser.
+All includes necessary for the compilation of the action code, must be provided at the top of the document.</p>
+</div>
+<div class="section" id="examples">
+<h2>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h2>
+<p>Some simple examples of models are provided below.
+This code only makes the specified models available in code; to do something with these models, an algorithms has to read out the model and operate on it.</p>
+<div class="section" id="petri-net-metamodel">
+<h3>Petri Net metamodel<a class="headerlink" href="#petri-net-metamodel" title="Permalink to this headline">¶</a></h3>
+<p>A simple Petri Net metamodel can be created, based on the SimpleClassDiagrams metamodel.
+This looks like this:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">models</span><span class="o">/</span><span class="n">SimpleClassDiagrams</span> <span class="k">as</span> <span class="n">SCD</span>
+
+<span class="n">SCD</span> <span class="n">PetriNets</span><span class="p">{</span>
+    <span class="n">Class</span> <span class="n">Natural</span> <span class="p">{}</span>
+    <span class="n">Class</span> <span class="n">Place</span><span class="p">{</span>
+        <span class="n">tokens</span> <span class="p">:</span> <span class="n">Natural</span>
+    <span class="p">}</span>
+    <span class="n">Class</span> <span class="n">Transition</span><span class="p">{}</span>
+    <span class="n">Association</span> <span class="n">P2T</span> <span class="p">(</span><span class="n">Place</span><span class="p">,</span> <span class="n">Transition</span><span class="p">)</span> <span class="p">{</span>
+        <span class="n">weight</span> <span class="p">:</span> <span class="n">Natural</span>
+    <span class="p">}</span>
+    <span class="n">Association</span> <span class="n">T2P</span> <span class="p">(</span><span class="n">Transition</span><span class="p">,</span> <span class="n">Place</span><span class="p">)</span> <span class="p">{</span>
+        <span class="n">weight</span> <span class="p">:</span> <span class="n">Natural</span>
+    <span class="p">}</span>
+<span class="p">}</span>
+
+<span class="n">export</span> <span class="n">PetriNets</span> <span class="n">to</span> <span class="n">models</span><span class="o">/</span><span class="n">PetriNets</span>
+</pre></div>
+</div>
+<p>Note that in this metamodel, there is no constraint placed on the value of a Natural: it can literaly be anything.
+That is why usually, you want to place constraints on the value.
+In this case, the value needs to be an integer, and it must be larger than or equal to zero.
+Such constraints are written in the action language, surrounded by dollar signs:</p>
+<div class="highlight-default"><div class="highlight"><pre>import models/SimpleClassDiagrams as SCD
+include &quot;primitives.alh&quot;
+
+SCD PetriNets{
+    Class Natural {
+        $
+            if (bool_not(is_physical_int(self))):
+                return &quot;Natural has no integer value at &quot; + name!
+            elif (integer_lt(self, 0)):
+                return &quot;Natural does not have a positive or zero value at &quot; + name!
+            else:
+                return &quot;OK&quot;!
+         $
+    }
+    Class Place{
+        tokens : Natural {
+            target_lower_cardinality = 1
+            target_upper_cardinality = 1
+            }
+    }
+    Class Transition{}
+    Association P2T (Place, Transition) {
+        weight : Natural {
+            target_lower_cardinality = 1
+            target_upper_cardinality = 1
+            }
+    }
+    Association T2P (Transition, Place) {
+        weight : Natural {
+            target_lower_cardinality = 1
+            target_upper_cardinality = 1
+            }
+    }
+}
+</pre></div>
+</div>
+</div>
+<div class="section" id="petri-net-instance">
+<h3>Petri Net instance<a class="headerlink" href="#petri-net-instance" title="Permalink to this headline">¶</a></h3>
+<p>The previous metamodel can then be instantiated:</p>
+<div class="highlight-default"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">models</span><span class="o">/</span><span class="n">PetriNets</span> <span class="k">as</span> <span class="n">PetriNets</span>
+
+<span class="n">PetriNets</span> <span class="n">my_petrinet</span> <span class="p">{</span>
+    <span class="n">Place</span> <span class="n">p1</span> <span class="p">{</span>
+        <span class="n">tokens</span> <span class="o">=</span> <span class="mi">1</span>
+    <span class="p">}</span>
+    <span class="n">Place</span> <span class="n">p2</span> <span class="p">{</span>
+        <span class="n">tokens</span> <span class="o">=</span> <span class="mi">3</span>
+    <span class="p">}</span>
+    <span class="n">Transition</span> <span class="n">t1</span> <span class="p">{}</span>
+    <span class="n">P2T</span> <span class="p">(</span><span class="n">p1</span><span class="p">,</span> <span class="n">t1</span><span class="p">)</span> <span class="p">{</span>
+        <span class="n">weight</span> <span class="o">=</span> <span class="mi">1</span>
+    <span class="p">}</span>
+    <span class="n">T2P</span> <span class="p">(</span><span class="n">t1</span><span class="p">,</span> <span class="n">p2</span><span class="p">)</span> <span class="p">{</span>
+        <span class="n">weight</span> <span class="o">=</span> <span class="mi">2</span>
+    <span class="p">}</span>
+<span class="p">}</span>
+
+<span class="n">export</span> <span class="n">my_petrinet</span> <span class="n">to</span> <span class="n">models</span><span class="o">/</span><span class="n">my_petrinet</span>
+</pre></div>
+</div>
+</div>
+</div>
+</div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
+        <div class="sphinxsidebarwrapper">
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Modelling Language</a><ul>
+<li><a class="reference internal" href="#language-description">Language description</a><ul>
+<li><a class="reference internal" href="#import">Import</a></li>
+<li><a class="reference internal" href="#include">Include</a></li>
+<li><a class="reference internal" href="#model">Model</a></li>
+<li><a class="reference internal" href="#instance">Instance</a></li>
+<li><a class="reference internal" href="#attribute">Attribute</a></li>
+</ul>
+</li>
+<li><a class="reference internal" href="#merge-with-action-language">Merge with Action Language</a></li>
+<li><a class="reference internal" href="#examples">Examples</a><ul>
+<li><a class="reference internal" href="#petri-net-metamodel">Petri Net metamodel</a></li>
+<li><a class="reference internal" href="#petri-net-instance">Petri Net instance</a></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="actionlanguage.html"
+                        title="previous chapter">Action Language</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="examples.html"
+                        title="next chapter">Examples</a></p>
+  <div role="note" aria-label="source link">
+    <h3>This Page</h3>
+    <ul class="this-page-menu">
+      <li><a href="_sources/modellanguage.txt"
+            rel="nofollow">Show Source</a></li>
+    </ul>
+   </div>
+<div id="searchbox" style="display: none" role="search">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <div><input type="text" name="q" /></div>
+      <div><input type="submit" value="Go" /></div>
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="examples.html" title="Examples"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="actionlanguage.html" title="Action Language"
+             >previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>
+    <div class="footer" role="contentinfo">
+        &#169; Copyright 2016, Yentl Van Tendeloo.
+      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.6.
+    </div>
+  </body>
+</html>

+ 120 - 0
doc/_build/html/models.html

@@ -0,0 +1,120 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Network interface &#8212; Modelverse 0.4.0 documentation</title>
+    
+    <link rel="stylesheet" href="_static/classic.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    './',
+        VERSION:     '0.4.0',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="Modelverse 0.4.0 documentation" href="index.html" />
+    <link rel="prev" title="Internal workings" href="internal.html" /> 
+  </head>
+  <body role="document">
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="internal.html" title="Internal workings"
+             accesskey="P">previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body" role="main">
+            
+  <div class="section" id="network-interface">
+<h1>Network interface<a class="headerlink" href="#network-interface" title="Permalink to this headline">¶</a></h1>
+<p>The network communication in the Modelverse builds on top of the raw socket implementation of Python.
+Whereas we use normal HTTP requests, we explicitly opted not to use these libraries.
+Many of these libraries hide important implementation details, such as how successive requests are handled (sequential, threaded, ...), whether or not to keep connections open and reuse them, which HTTP version to implement, and so on.
+As the HTTP protocol is a simple protocol, we reimplemented it completely in SCCD (StateCharts and Class Diagrams).</p>
+<p>There are two network components: a server in the MvS, and a server and client in the MvK.
+These are discussed next.</p>
+<div class="section" id="mvs-server">
+<h2>MvS server<a class="headerlink" href="#mvs-server" title="Permalink to this headline">¶</a></h2>
+<img alt="_images/mvs_server.svg" src="_images/mvs_server.svg" /></div>
+<div class="section" id="mvk-server">
+<h2>MvK server<a class="headerlink" href="#mvk-server" title="Permalink to this headline">¶</a></h2>
+<img alt="_images/mvk_server.svg" src="_images/mvk_server.svg" /></div>
+</div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
+        <div class="sphinxsidebarwrapper">
+  <h3><a href="index.html">Table Of Contents</a></h3>
+  <ul>
+<li><a class="reference internal" href="#">Network interface</a><ul>
+<li><a class="reference internal" href="#mvs-server">MvS server</a></li>
+<li><a class="reference internal" href="#mvk-server">MvK server</a></li>
+</ul>
+</li>
+</ul>
+
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="internal.html"
+                        title="previous chapter">Internal workings</a></p>
+  <div role="note" aria-label="source link">
+    <h3>This Page</h3>
+    <ul class="this-page-menu">
+      <li><a href="_sources/models.txt"
+            rel="nofollow">Show Source</a></li>
+    </ul>
+   </div>
+<div id="searchbox" style="display: none" role="search">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <div><input type="text" name="q" /></div>
+      <div><input type="submit" value="Go" /></div>
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="internal.html" title="Internal workings"
+             >previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>
+    <div class="footer" role="contentinfo">
+        &#169; Copyright 2016, Yentl Van Tendeloo.
+      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.6.
+    </div>
+  </body>
+</html>

BIN
doc/_build/html/objects.inv


+ 109 - 0
doc/_build/html/problems.html

@@ -0,0 +1,109 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    
+    <title>Common problems and solutions &#8212; Modelverse 0.4.0 documentation</title>
+    
+    <link rel="stylesheet" href="_static/classic.css" type="text/css" />
+    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
+    
+    <script type="text/javascript">
+      var DOCUMENTATION_OPTIONS = {
+        URL_ROOT:    './',
+        VERSION:     '0.4.0',
+        COLLAPSE_INDEX: false,
+        FILE_SUFFIX: '.html',
+        HAS_SOURCE:  true
+      };
+    </script>
+    <script type="text/javascript" src="_static/jquery.js"></script>
+    <script type="text/javascript" src="_static/underscore.js"></script>
+    <script type="text/javascript" src="_static/doctools.js"></script>
+    <link rel="top" title="Modelverse 0.4.0 documentation" href="index.html" />
+    <link rel="next" title="Internal workings" href="internal.html" />
+    <link rel="prev" title="Advanced examples" href="advanced.html" /> 
+  </head>
+  <body role="document">
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             accesskey="I">index</a></li>
+        <li class="right" >
+          <a href="internal.html" title="Internal workings"
+             accesskey="N">next</a> |</li>
+        <li class="right" >
+          <a href="advanced.html" title="Advanced examples"
+             accesskey="P">previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>  
+
+    <div class="document">
+      <div class="documentwrapper">
+        <div class="bodywrapper">
+          <div class="body" role="main">
+            
+  <div class="section" id="common-problems-and-solutions">
+<h1>Common problems and solutions<a class="headerlink" href="#common-problems-and-solutions" title="Permalink to this headline">¶</a></h1>
+</div>
+
+
+          </div>
+        </div>
+      </div>
+      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
+        <div class="sphinxsidebarwrapper">
+  <h4>Previous topic</h4>
+  <p class="topless"><a href="advanced.html"
+                        title="previous chapter">Advanced examples</a></p>
+  <h4>Next topic</h4>
+  <p class="topless"><a href="internal.html"
+                        title="next chapter">Internal workings</a></p>
+  <div role="note" aria-label="source link">
+    <h3>This Page</h3>
+    <ul class="this-page-menu">
+      <li><a href="_sources/problems.txt"
+            rel="nofollow">Show Source</a></li>
+    </ul>
+   </div>
+<div id="searchbox" style="display: none" role="search">
+  <h3>Quick search</h3>
+    <form class="search" action="search.html" method="get">
+      <div><input type="text" name="q" /></div>
+      <div><input type="submit" value="Go" /></div>
+      <input type="hidden" name="check_keywords" value="yes" />
+      <input type="hidden" name="area" value="default" />
+    </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+        </div>
+      </div>
+      <div class="clearer"></div>
+    </div>
+    <div class="related" role="navigation" aria-label="related navigation">
+      <h3>Navigation</h3>
+      <ul>
+        <li class="right" style="margin-right: 10px">
+          <a href="genindex.html" title="General Index"
+             >index</a></li>
+        <li class="right" >
+          <a href="internal.html" title="Internal workings"
+             >next</a> |</li>
+        <li class="right" >
+          <a href="advanced.html" title="Advanced examples"
+             >previous</a> |</li>
+        <li class="nav-item nav-item-0"><a href="index.html">Modelverse 0.4.0 documentation</a> &#187;</li> 
+      </ul>
+    </div>
+    <div class="footer" role="contentinfo">
+        &#169; Copyright 2016, Yentl Van Tendeloo.
+      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.6.
+    </div>
+  </body>
+</html>

+ 0 - 0
doc/_build/html/search.html


Некоторые файлы не были показаны из-за большого количества измененных файлов