Explorar o código

Added test suite for generated Modelverse Kernel

Yentl Van Tendeloo %!s(int64=7) %!d(string=hai) anos
pai
achega
61fe880b45
Modificáronse 48 ficheiros con 7102 adicións e 0 borrados
  1. 0 0
      kernel/test_generated/__init__.py
  2. 0 0
      kernel/test_generated/instructions/__init__.py
  3. 65 0
      kernel/test_generated/instructions/test_instruction_access.py
  4. 88 0
      kernel/test_generated/instructions/test_instruction_assign.py
  5. 99 0
      kernel/test_generated/instructions/test_instruction_break.py
  6. 487 0
      kernel/test_generated/instructions/test_instruction_call.py
  7. 158 0
      kernel/test_generated/instructions/test_instruction_continue.py
  8. 58 0
      kernel/test_generated/instructions/test_instruction_declare.py
  9. 282 0
      kernel/test_generated/instructions/test_instruction_if.py
  10. 44 0
      kernel/test_generated/instructions/test_instruction_input.py
  11. 130 0
      kernel/test_generated/instructions/test_instruction_output.py
  12. 97 0
      kernel/test_generated/instructions/test_instruction_resolve.py
  13. 76 0
      kernel/test_generated/instructions/test_instruction_return.py
  14. 305 0
      kernel/test_generated/instructions/test_instruction_while.py
  15. 120 0
      kernel/test_generated/instructions/utils.py
  16. 0 0
      kernel/test_generated/primitives/__init__.py
  17. 182 0
      kernel/test_generated/primitives/test_action.py
  18. 240 0
      kernel/test_generated/primitives/test_bool.py
  19. 196 0
      kernel/test_generated/primitives/test_cast.py
  20. 258 0
      kernel/test_generated/primitives/test_create.py
  21. 149 0
      kernel/test_generated/primitives/test_delete.py
  22. 338 0
      kernel/test_generated/primitives/test_dict.py
  23. 255 0
      kernel/test_generated/primitives/test_dict_special.py
  24. 108 0
      kernel/test_generated/primitives/test_edge.py
  25. 138 0
      kernel/test_generated/primitives/test_element.py
  26. 225 0
      kernel/test_generated/primitives/test_float.py
  27. 225 0
      kernel/test_generated/primitives/test_integer.py
  28. 327 0
      kernel/test_generated/primitives/test_list.py
  29. 386 0
      kernel/test_generated/primitives/test_read.py
  30. 367 0
      kernel/test_generated/primitives/test_string.py
  31. 120 0
      kernel/test_generated/primitives/utils.py
  32. 0 0
      kernel/test_generated/rules/__init__.py
  33. 65 0
      kernel/test_generated/rules/test_rules_access.py
  34. 105 0
      kernel/test_generated/rules/test_rules_assign.py
  35. 43 0
      kernel/test_generated/rules/test_rules_break.py
  36. 397 0
      kernel/test_generated/rules/test_rules_call.py
  37. 35 0
      kernel/test_generated/rules/test_rules_constant.py
  38. 43 0
      kernel/test_generated/rules/test_rules_continue.py
  39. 63 0
      kernel/test_generated/rules/test_rules_helper.py
  40. 128 0
      kernel/test_generated/rules/test_rules_if.py
  41. 67 0
      kernel/test_generated/rules/test_rules_input.py
  42. 70 0
      kernel/test_generated/rules/test_rules_output.py
  43. 115 0
      kernel/test_generated/rules/test_rules_resolve.py
  44. 86 0
      kernel/test_generated/rules/test_rules_return.py
  45. 28 0
      kernel/test_generated/rules/test_rules_utility.py
  46. 94 0
      kernel/test_generated/rules/test_rules_while.py
  47. 120 0
      kernel/test_generated/rules/utils.py
  48. 120 0
      kernel/test_generated/utils.py

+ 0 - 0
kernel/test_generated/__init__.py


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


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

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

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

@@ -0,0 +1,88 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_returnvalue_ref, get_inst_ref
+
+class TestAssign(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+    def test_assign_simple(self):
+        """
+        Test the code:
+            a = True
+        """
+        self.var = self.mvs.execute("CN", [])
+        self.value = self.mvs.execute("CN", [])
+        self.previous = self.mvs.execute("CN", [])
+        self.const = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_value = self.mvs.execute("CNV", [True])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"assign"}])
+        self.resolve = self.mvs.execute("CNV", [{"value":"resolve"}])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "var", self.resolve])
+        self.mvs.execute("CD", [self.inst, "value", self.const])
+        self.mvs.execute("CD", [self.resolve, "var", self.var])
+        self.mvs.execute("CD", [self.value, "value", self.previous])
+        self.mvs.execute("CD", [self.const, "node", self.const_value])
+        t = self.mvs.execute("CE", [self.symbols, self.value])
+        self.mvs.execute("CE", [t, self.var])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "assign")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "assign")
+        self.assertEquals(get_phase(self.root, self.mvs), "value")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "assign")
+        self.assertEquals(get_phase(self.root, self.mvs), "assign")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "assign")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+
+        # Check if the new value is really assigned
+        t = self.mvs.execute("RD", [self.root, "task_1"])
+        t = self.mvs.execute("RD", [t, "frame"])
+        t = self.mvs.execute("RD", [t, "symbols"])
+        t = self.mvs.execute("RDN", [t, self.var])
+        t = self.mvs.execute("RD", [t, "value"])
+        t = self.mvs.execute("RV", [t])
+        self.assertEquals(t, True)

+ 99 - 0
kernel/test_generated/instructions/test_instruction_break.py

@@ -0,0 +1,99 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue
+
+class TestBreak(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+    def test_break(self):
+        """
+        Test the code:
+            while True:
+                a
+                break
+            c
+        """
+        self.inst = self.mvs.execute("CNV", [{"value":"while"}])
+
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_cond = self.mvs.execute("CNV", [{"value":"constant"}])
+
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_cond = self.mvs.execute("CNV", [True])
+        self.break_inst = self.mvs.execute("CNV", [{"value":"break"}])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "cond", self.const_cond])
+        self.mvs.execute("CD", [self.inst, "body", self.const_a])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "next", self.break_inst])
+        self.mvs.execute("CD", [self.break_inst, "while", self.inst])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_cond, "node", self.value_cond])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), True)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "break")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "break")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")

+ 487 - 0
kernel/test_generated/instructions/test_instruction_call.py

@@ -0,0 +1,487 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref
+
+class Testcall(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+    def test_no_params(self):
+        """
+        Test the code:
+            def function_A():
+                return
+
+            function_A()
+            a
+        """
+        self.params = self.mvs.execute("CN", [])
+        self.var_function = self.mvs.execute("CN", [])
+        self.signature = self.mvs.execute("CN", [])
+        self.val_function = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.access = self.mvs.execute("CNV", [{"value":"access"}])
+        self.resolve = self.mvs.execute("CNV", [{"value":"resolve"}])
+        self.ret = self.mvs.execute("CNV", [{"value":"return"}])
+
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "func", self.access])
+        self.mvs.execute("CD", [self.inst, "next", self.const_a])
+        self.mvs.execute("CD", [self.access, "var", self.resolve])
+        self.mvs.execute("CD", [self.resolve, "var", self.var_function])
+        self.mvs.execute("CD", [self.val_function, "value", self.signature])
+        self.mvs.execute("CD", [self.signature, "body", self.ret])
+        self.mvs.execute("CD", [self.signature, "params", self.params])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        t = self.mvs.execute("CE", [self.symbols, self.val_function])
+        self.mvs.execute("CE", [t, self.var_function])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "eval")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "return")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+
+    def test_single_param(self):
+        """
+        Test the code:
+            def function_A(abc):
+                return
+
+            function_A(abc="def")
+            a
+        """
+        self.params = self.mvs.execute("CN", [])
+        self.var_function = self.mvs.execute("CN", [])
+        self.signature = self.mvs.execute("CN", [])
+        self.val_function = self.mvs.execute("CN", [])
+        self.var_abc = self.mvs.execute("CN", [])
+        self.actual_arg = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.access = self.mvs.execute("CNV", [{"value":"access"}])
+        self.resolve = self.mvs.execute("CNV", [{"value":"resolve"}])
+        self.ret = self.mvs.execute("CNV", [{"value":"return"}])
+
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_def = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_abc = self.mvs.execute("CNV", ["abc"])
+        self.value_def = self.mvs.execute("CNV", ["def"])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "func", self.access])
+        self.mvs.execute("CD", [self.inst, "next", self.const_a])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg])
+        self.mvs.execute("CD", [self.actual_arg, "value", self.const_def])
+        self.mvs.execute("CD", [self.actual_arg, "name", self.mvs.execute("CNV", ["abc"])])
+        self.mvs.execute("CD", [self.const_def, "node", self.value_def])
+        self.mvs.execute("CD", [self.access, "var", self.resolve])
+        self.mvs.execute("CD", [self.resolve, "var", self.var_function])
+        self.mvs.execute("CD", [self.val_function, "value", self.signature])
+        self.mvs.execute("CD", [self.signature, "body", self.ret])
+        self.mvs.execute("CD", [self.signature, "params", self.params])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        t = self.mvs.execute("CE", [self.symbols, self.val_function])
+        self.mvs.execute("CE", [t, self.var_function])
+        self.mvs.execute("CD", [self.params, "abc", self.var_abc])
+        self.mvs.execute("CD", [self.var_abc, "name", self.value_abc])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "eval")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "return")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+
+    def test_two_params(self):
+        """
+        Test the code:
+            def function_A(a, b):
+                return
+
+            function_A(a="d", b="e")
+            f
+        """
+        self.params = self.mvs.execute("CN", [])
+        self.var_function = self.mvs.execute("CN", [])
+        self.signature = self.mvs.execute("CN", [])
+        self.val_function = self.mvs.execute("CN", [])
+        self.var_a = self.mvs.execute("CN", [])
+        self.var_b = self.mvs.execute("CN", [])
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.access = self.mvs.execute("CNV", [{"value":"access"}])
+        self.resolve = self.mvs.execute("CNV", [{"value":"resolve"}])
+        self.ret = self.mvs.execute("CNV", [{"value":"return"}])
+
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_d = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_e = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_f = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_d = self.mvs.execute("CNV", ["d"])
+        self.value_e = self.mvs.execute("CNV", ["e"])
+        self.value_f = self.mvs.execute("CNV", ["f"])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "func", self.access])
+        self.mvs.execute("CD", [self.inst, "next", self.const_a])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_d])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.mvs.execute("CNV", ["a"])])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_e])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.mvs.execute("CNV", ["b"])])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_d, "node", self.value_d])
+        self.mvs.execute("CD", [self.const_e, "node", self.value_e])
+        self.mvs.execute("CD", [self.const_f, "node", self.value_f])
+        self.mvs.execute("CD", [self.access, "var", self.resolve])
+        self.mvs.execute("CD", [self.resolve, "var", self.var_function])
+        self.mvs.execute("CD", [self.val_function, "value", self.signature])
+        self.mvs.execute("CD", [self.signature, "body", self.ret])
+        self.mvs.execute("CD", [self.signature, "params", self.params])
+        t = self.mvs.execute("CE", [self.symbols, self.val_function])
+        self.mvs.execute("CE", [t, self.var_function])
+        self.mvs.execute("CD", [self.params, "a", self.var_a])
+        self.mvs.execute("CD", [self.params, "b", self.var_b])
+        self.mvs.execute("CD", [self.var_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.var_b, "name", self.value_b])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "eval")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "return")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+
+    def test_three_params(self):
+        """
+        Test the code:
+            def function_A(a, b, c):
+                return
+
+            function_A(a="d", b="e", c="f")
+            f
+        """
+        self.params = self.mvs.execute("CN", [])
+        self.var_function = self.mvs.execute("CN", [])
+        self.signature = self.mvs.execute("CN", [])
+        self.val_function = self.mvs.execute("CN", [])
+        self.var_a = self.mvs.execute("CN", [])
+        self.var_b = self.mvs.execute("CN", [])
+        self.var_c = self.mvs.execute("CN", [])
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+        self.actual_arg_c = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.access = self.mvs.execute("CNV", [{"value":"access"}])
+        self.resolve = self.mvs.execute("CNV", [{"value":"resolve"}])
+        self.ret = self.mvs.execute("CNV", [{"value":"return"}])
+
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_d = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_e = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_f = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_d = self.mvs.execute("CNV", ["d"])
+        self.value_e = self.mvs.execute("CNV", ["e"])
+        self.value_f = self.mvs.execute("CNV", ["f"])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "func", self.access])
+        self.mvs.execute("CD", [self.inst, "next", self.const_a])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_b, "next_param", self.actual_arg_c])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_c])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_d])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.mvs.execute("CNV", ["a"])])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_e])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.mvs.execute("CNV", ["b"])])
+        self.mvs.execute("CD", [self.actual_arg_c, "value", self.const_f])
+        self.mvs.execute("CD", [self.actual_arg_c, "name", self.mvs.execute("CNV", ["c"])])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_d, "node", self.value_d])
+        self.mvs.execute("CD", [self.const_e, "node", self.value_e])
+        self.mvs.execute("CD", [self.const_f, "node", self.value_f])
+        self.mvs.execute("CD", [self.access, "var", self.resolve])
+        self.mvs.execute("CD", [self.resolve, "var", self.var_function])
+        self.mvs.execute("CD", [self.val_function, "value", self.signature])
+        self.mvs.execute("CD", [self.signature, "body", self.ret])
+        self.mvs.execute("CD", [self.signature, "params", self.params])
+        t = self.mvs.execute("CE", [self.symbols, self.val_function])
+        self.mvs.execute("CE", [t, self.var_function])
+        self.mvs.execute("CD", [self.params, "a", self.var_a])
+        self.mvs.execute("CD", [self.params, "b", self.var_b])
+        self.mvs.execute("CD", [self.params, "c", self.var_c])
+        self.mvs.execute("CD", [self.var_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.var_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.var_c, "name", self.value_c])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "eval")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "access")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_c)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "return")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")

+ 158 - 0
kernel/test_generated/instructions/test_instruction_continue.py

@@ -0,0 +1,158 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue
+
+class Testcontinue(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+    def test_continue(self):
+        """
+        Test the code:
+            while True:
+                a
+                continue
+            c
+        """
+        self.inst = self.mvs.execute("CNV", [{"value":"while"}])
+
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_cond = self.mvs.execute("CNV", [{"value":"constant"}])
+
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_cond = self.mvs.execute("CNV", [True])
+        self.continue_inst = self.mvs.execute("CNV", [{"value":"continue"}])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "cond", self.const_cond])
+        self.mvs.execute("CD", [self.inst, "body", self.const_a])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "next", self.continue_inst])
+        self.mvs.execute("CD", [self.continue_inst, "while", self.inst])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_cond, "node", self.value_cond])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), True)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "continue")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "continue")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Loop 2
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), True)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "continue")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "continue")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Loop 3
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), True)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "continue")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "continue")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+

+ 58 - 0
kernel/test_generated/instructions/test_instruction_declare.py

@@ -0,0 +1,58 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue
+
+class TestDeclare(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.globals = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_root, "globals", self.globals])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+    def test_declare(self):
+        self.inst = self.mvs.execute("CNV", [{"value":"declare"}])
+        self.var = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "var", self.var])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "declare")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "declare")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertNotEquals(self.mvs.execute("RDN", [self.symbols, self.var]), None)
+
+    def test_global(self):
+        self.global_symbols = self.mvs.execute("RD", [self.task_root, "globals"])
+        self.inst = self.mvs.execute("CNV", [{"value":"global"}])
+        self.var = self.mvs.execute("CNV", ["abc"])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "var", self.var])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "global")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "global")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertNotEquals(self.mvs.execute("RD", [self.global_symbols, "abc"]), None)

+ 282 - 0
kernel/test_generated/instructions/test_instruction_if.py

@@ -0,0 +1,282 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue
+
+class Testif(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+    def test_if_true_with_else(self):
+        """
+        Test the code:
+            if True:
+                a
+            else:
+                b
+            c
+        """
+        self.inst = self.mvs.execute("CNV", [{"value":"if"}])
+
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_true = self.mvs.execute("CNV", [{"value":"constant"}])
+
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_true = self.mvs.execute("CNV", [True])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "cond", self.const_true])
+        self.mvs.execute("CD", [self.inst, "then", self.const_a])
+        self.mvs.execute("CD", [self.inst, "else", self.const_b])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_true, "node", self.value_true])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "if")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), True)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "if")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "if")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")
+
+    def test_if_true_without_else(self):
+        """
+        Test the code:
+            if True:
+                a
+            c
+        """
+        self.inst = self.mvs.execute("CNV", [{"value":"if"}])
+
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_true = self.mvs.execute("CNV", [{"value":"constant"}])
+
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_true = self.mvs.execute("CNV", [True])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "cond", self.const_true])
+        self.mvs.execute("CD", [self.inst, "then", self.const_a])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_true, "node", self.value_true])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "if")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), True)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "if")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "if")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")
+
+    def test_if_false_with_else(self):
+        """
+        Test the code:
+            if False:
+                a
+            else:
+                b
+            c
+        """
+        self.inst = self.mvs.execute("CNV", [{"value":"if"}])
+
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_false = self.mvs.execute("CNV", [{"value":"constant"}])
+
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_false = self.mvs.execute("CNV", [False])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "cond", self.const_false])
+        self.mvs.execute("CD", [self.inst, "then", self.const_a])
+        self.mvs.execute("CD", [self.inst, "else", self.const_b])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_false, "node", self.value_false])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "if")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), False)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "if")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "b")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "if")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")
+
+    def test_if_false_without_else(self):
+        """
+        Test the code:
+            if False:
+                a
+            c
+        """
+        self.inst = self.mvs.execute("CNV", [{"value":"if"}])
+
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_false = self.mvs.execute("CNV", [{"value":"constant"}])
+
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_false = self.mvs.execute("CNV", [False])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "cond", self.const_false])
+        self.mvs.execute("CD", [self.inst, "then", self.const_a])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_false, "node", self.value_false])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "if")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), False)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "if")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "if")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")

+ 44 - 0
kernel/test_generated/instructions/test_instruction_input.py

@@ -0,0 +1,44 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue_ref
+
+class TestInput(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.task_input = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "input", self.task_input])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+    def test_input(self):
+        self.input_value = self.mvs.execute("CN", [])
+        self.inst = self.mvs.execute("CNV", [{"value":"input"}])
+
+        self.value_a = self.mvs.execute("CNV", ["a"])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.task_input, "next", self.input_value])
+        self.mvs.execute("CD", [self.task_input, "value", self.value_a])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "input")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "input")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_a)

+ 130 - 0
kernel/test_generated/instructions/test_instruction_output.py

@@ -0,0 +1,130 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue_ref
+
+class TestOutput(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.task_input = self.mvs.execute("CN", [])
+        self.task_output = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "input", self.task_input])
+        self.mvs.execute("CD", [self.task_root, "last_input", self.task_input])
+        self.mvs.execute("CD", [self.task_root, "output", self.task_output])
+        self.mvs.execute("CD", [self.task_root, "last_output", self.task_output])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+    def test_output_value(self):
+        self.input_value = self.mvs.execute("CN", [])
+        self.inst = self.mvs.execute("CNV", [{"value":"output"}])
+
+        self.const = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "value", self.const])
+        self.mvs.execute("CD", [self.const, "node", self.value_a])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "output")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "output")
+        self.assertEquals(get_phase(self.root, self.mvs), "output")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "output")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [self.task_output, "value"])]), "a")
+
+    def test_output_node(self):
+        self.input_value = self.mvs.execute("CN", [])
+        self.inst = self.mvs.execute("CNV", [{"value":"output"}])
+
+        self.const = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "value", self.const])
+        self.mvs.execute("CD", [self.const, "node", self.value])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "output")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "output")
+        self.assertEquals(get_phase(self.root, self.mvs), "output")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "output")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(self.mvs.execute("RD", [self.task_output, "value"]), self.value)
+
+    def test_output_edge(self):
+        self.input_value = self.mvs.execute("CN", [])
+        self.inst = self.mvs.execute("CNV", [{"value":"output"}])
+
+        self.const = self.mvs.execute("CNV", [{"value":"constant"}])
+        a = self.mvs.execute("CN", [])
+        b = self.mvs.execute("CN", [])
+        self.value = self.mvs.execute("CE", [a,b])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "value", self.const])
+        self.mvs.execute("CD", [self.const, "node", self.value])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "output")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "output")
+        self.assertEquals(get_phase(self.root, self.mvs), "output")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "output")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(self.mvs.execute("RD", [self.task_output, "value"]), self.value)

+ 97 - 0
kernel/test_generated/instructions/test_instruction_resolve.py

@@ -0,0 +1,97 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_returnvalue_ref, get_inst_ref
+
+class Testresolve(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.global_task = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_root, "globals", self.global_task])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+    def test_resolve_simple_local(self):
+        """
+        Test the resolution of a local variable
+        """
+        self.var = self.mvs.execute("CN", [])
+        self.value = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"resolve"}])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "var", self.var])
+        t = self.mvs.execute("CE", [self.symbols, self.value])
+        self.mvs.execute("CE", [t, self.var])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value)
+
+    def test_resolve_simple_global(self):
+        """
+        Test the resolution of a global variable
+        """
+        self.var = self.mvs.execute("CNV", ["glob"])
+        self.value = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"resolve"}])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "var", self.var])
+        t = self.mvs.execute("CE", [self.global_task, self.value])
+        self.mvs.execute("CE", [t, self.var])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value)
+
+    def test_resolve_simple_local_over_global(self):
+        """
+        Test the resolution of a local variable over a global
+        """
+        self.var = self.mvs.execute("CNV", ["local"])
+        self.global_value = self.mvs.execute("CN", [])
+        self.local_value = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"resolve"}])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "var", self.var])
+        t = self.mvs.execute("CE", [self.global_task, self.global_value])
+        self.mvs.execute("CE", [t, self.var])
+        t = self.mvs.execute("CE", [self.symbols, self.local_value])
+        self.mvs.execute("CE", [t, self.var])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "resolve")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.local_value)

+ 76 - 0
kernel/test_generated/instructions/test_instruction_return.py

@@ -0,0 +1,76 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue
+
+class Testreturn(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+    def test_return(self):
+        """
+        Test the code:
+            return True
+        """
+        prev_task_frame = self.mvs.execute("CN", [])
+        prev_symbols = self.mvs.execute("CN", [])
+        prev_evalstack = self.mvs.execute("CN", [])
+        prev_returnvalue = self.mvs.execute("CN", [])
+        prev_phase = self.mvs.execute("CNV", ["init"])
+        prev_IP = self.mvs.execute("CNV", [{"value":"constant"}])
+
+        self.mvs.execute("CD", [self.task_frame, "prev", prev_task_frame])
+        self.mvs.execute("CD", [prev_task_frame, "symbols", prev_symbols])
+        self.mvs.execute("CD", [prev_task_frame, "evalstack", prev_evalstack])
+        self.mvs.execute("CD", [prev_task_frame, "phase", prev_phase])
+        self.mvs.execute("CD", [prev_task_frame, "IP", prev_IP])
+        self.mvs.execute("CD", [prev_task_frame, "returnvalue", prev_returnvalue])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"return"}])
+        self.const_true = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_true = self.mvs.execute("CNV", [True])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "value", self.const_true])
+        self.mvs.execute("CD", [self.const_true, "node", self.value_true])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "return")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), True)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "return")
+        self.assertEquals(get_phase(self.root, self.mvs), "eval")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), True)
+
+        t = self.mvs.execute("RD", [self.root, "task_1"])
+        t = self.mvs.execute("RD", [t, "frame"])
+        self.assertEquals(t, prev_task_frame)

+ 305 - 0
kernel/test_generated/instructions/test_instruction_while.py

@@ -0,0 +1,305 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue
+
+class Testwhile(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+    def test_while_true(self):
+        """
+        Test the code:
+            while True:
+                a
+            b
+        """
+        self.inst = self.mvs.execute("CNV", [{"value":"while"}])
+
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_cond = self.mvs.execute("CNV", [{"value":"constant"}])
+
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_cond = self.mvs.execute("CNV", [True])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "cond", self.const_cond])
+        self.mvs.execute("CD", [self.inst, "body", self.const_a])
+        self.mvs.execute("CD", [self.inst, "next", self.const_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_cond, "node", self.value_cond])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), True)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Loop 2
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), True)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Loop 3
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), True)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+
+        # This will keep on going
+
+    def test_while_false(self):
+        """
+        Test the code:
+            while False:
+                a
+            b
+        """
+        self.inst = self.mvs.execute("CNV", [{"value":"while"}])
+
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_cond = self.mvs.execute("CNV", [{"value":"constant"}])
+
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_cond = self.mvs.execute("CNV", [False])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "cond", self.const_cond])
+        self.mvs.execute("CD", [self.inst, "body", self.const_a])
+        self.mvs.execute("CD", [self.inst, "next", self.const_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_cond, "node", self.value_cond])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), False)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "b")
+
+    def test_while_variable(self):
+        """
+        Test the code:
+            while True:
+                a
+            b
+        But where the True changes to a False after 2 iterations
+        """
+        self.inst = self.mvs.execute("CNV", [{"value":"while"}])
+
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_cond = self.mvs.execute("CNV", [{"value":"constant"}])
+
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_cond = self.mvs.execute("CNV", [True])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.mvs.execute("CD", [self.inst, "cond", self.const_cond])
+        self.mvs.execute("CD", [self.inst, "body", self.const_a])
+        self.mvs.execute("CD", [self.inst, "next", self.const_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_cond, "node", self.value_cond])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), True)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Loop 2
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), True)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "a")
+        execute_until_finished(self.mvk, self.mvs)
+
+        #####
+        # Modify the constant to force the loop to stop
+        #####
+
+        new_const_cond = self.mvs.execute("CNV", [False])
+        self.mvs.execute("DN", [self.value_cond])
+        self.mvs.execute("CD", [self.const_cond, "node", new_const_cond])
+
+        ##### Modifications done
+
+        # Loop 3
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), False)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "cond")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "while")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "b")

+ 120 - 0
kernel/test_generated/instructions/utils.py

@@ -0,0 +1,120 @@
+import sys
+sys.path.append("../state")
+from modelverse_state.main import ModelverseState
+import json
+
+class MvSWrapper(object):
+    def __init__(self):
+        self.mvs = ModelverseState("../bootstrap/minimal.m.gz")
+
+        self.mapping = {
+                   "RD": self.mvs.read_dict,
+                   "RR": self.mvs.read_root,
+                   "RO": self.mvs.read_outgoing,
+                   "RI": self.mvs.read_incoming,
+                   "RE": self.mvs.read_edge,
+                   "RDE": self.mvs.read_dict_edge,
+                   "RDK": self.mvs.read_dict_keys,
+                   "RDN": self.mvs.read_dict_node,
+                   "RDNE": self.mvs.read_dict_node_edge,
+                   "RRD": self.mvs.read_reverse_dict,
+                   "RV": self.mvs.read_value,
+                   "CN": self.mvs.create_node,
+                   "CNV": self.mvs.create_nodevalue,
+                   "CE": self.mvs.create_edge,
+                   "DE": self.mvs.delete_edge,
+                   "DN": self.mvs.delete_node,
+                   "CD": self.mvs.create_dict,
+                  }
+
+    def execute(self, command, params):
+        params = json.loads(json.dumps(params))
+        retval = self.mapping[command](*params)
+        retval = json.loads(json.dumps(retval))
+
+        return retval
+
+def add_new_task(root, mvs, taskname):
+    hierarchy = mvs.execute("RD", [root, "__hierarchy"])
+    initial = mvs.execute("RD", [hierarchy, "__IP"])
+
+    task_root = mvs.execute("CN", [])
+    _globals = mvs.execute("CN", [])
+    frame = mvs.execute("CN", [])
+    evalstack = mvs.execute("CN", [])
+    symbols = mvs.execute("CN", [])
+    _input = mvs.execute("CN", [])
+    _output = mvs.execute("CN", [])
+    returnvalue = mvs.execute("CN", [])
+    phase = mvs.execute("CNV", ["init"])
+
+    mvs.execute("CD", [root, taskname, task_root])
+    mvs.execute("CD", [task_root, "frame", frame])
+    mvs.execute("CD", [task_root, "globals", _globals])
+    mvs.execute("CD", [task_root, "input", _input])
+    mvs.execute("CD", [task_root, "last_input", _input])
+    mvs.execute("CD", [task_root, "output", _output])
+    mvs.execute("CD", [task_root, "last_output", _output])
+    mvs.execute("CD", [frame, "evalstack", evalstack])
+    mvs.execute("CD", [frame, "returnvalue", returnvalue])
+    mvs.execute("CD", [frame, "phase", phase])
+    mvs.execute("CD", [frame, "IP", initial])
+    mvs.execute("CD", [frame, "symbols", symbols])
+
+def execute_until_finished(mvk, mvs, operation="execute_rule", params=[]):
+    taskname = "task_1"
+    if operation == "initialize_new_task":
+        return add_new_task(mvk.root, mvs, taskname)
+    response = None
+    while 1:
+        mvs_commands = mvk.execute_yields(taskname, operation, params, response)
+        if mvs_commands is None:
+            break
+        response = []
+        for command, param in mvs_commands:
+            response.append(mvs.execute(command, param))
+
+def get_inst(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    inst = mvs.execute("RD", [task_frame, "IP"])
+    return mvs.execute("RV", [inst])["value"]
+
+def get_phase(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    phase = mvs.execute("RD", [task_frame, "phase"])
+    return mvs.execute("RV", [phase])
+
+def get_returnvalue(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    returnvalue = mvs.execute("RD", [task_frame, "returnvalue"])
+    return mvs.execute("RV", [returnvalue])
+
+def get_inst_ref(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    return mvs.execute("RD", [task_frame, "IP"])
+
+def get_returnvalue_ref(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    return mvs.execute("RD", [task_frame, "returnvalue"])
+
+def get_phase_ref(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    phase = mvs.execute("RD", [task_frame, "phase"])
+    return phase
+
+def read_primitive_interfaces(root, mvs):
+    hierarchy = mvs.execute("RD", [root, "__hierarchy"])
+    primitives = mvs.execute("RD", [hierarchy, "primitives"])
+    keys = mvs.execute("RDK", [primitives])
+    d = {}
+    for k in keys:
+        value = mvs.execute("RDN", [primitives, k])
+        name = mvs.execute("RV", [k])
+        d[name] = value
+    return d

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


+ 182 - 0
kernel/test_generated/primitives/test_action.py

@@ -0,0 +1,182 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces
+
+class TestAction(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_eq_true(self):
+        self.helper_primitives_2_params("value_eq", {"value": "while"}, {"value": "while"}, True)
+
+    def test_eq_false(self):
+        self.helper_primitives_2_params("value_eq", {"value": "while"}, {"value": "call"}, False)
+
+    def test_eq_diff(self):
+        self.helper_primitives_2_params("value_eq", {"value": "while"}, 10, False)
+
+    def helper_primitives_2_params(self, operation, a, b, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CNV", [a])
+        self.value_second = self.mvs.execute("CNV", [b])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), result)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")
+
+    def helper_primitives_1_params(self, operation, a, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CNV", [a])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")

+ 240 - 0
kernel/test_generated/primitives/test_bool.py

@@ -0,0 +1,240 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces
+
+class TestBool(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_and_T_T(self):
+        self.helper_primitives_2_params("bool_and", True, True, True)
+
+    def test_and_T_F(self):
+        self.helper_primitives_2_params("bool_and", True, False, False)
+
+    def test_and_F_T(self):
+        self.helper_primitives_2_params("bool_and", False, True, False)
+
+    def test_and_F_F(self):
+        self.helper_primitives_2_params("bool_and", False, False, False)
+
+    def test_or_T_T(self):
+        self.helper_primitives_2_params("bool_or", True, True, True)
+
+    def test_or_T_F(self):
+        self.helper_primitives_2_params("bool_or", True, False, True)
+
+    def test_or_F_T(self):
+        self.helper_primitives_2_params("bool_or", False, True, True)
+
+    def test_or_F_F(self):
+        self.helper_primitives_2_params("bool_or", False, False, False)
+
+    def test_not_T(self):
+        self.helper_primitives_1_params("bool_not", True, False)
+
+    def test_not_F(self):
+        self.helper_primitives_1_params("bool_not", False, True)
+
+    def test_eq_T_T(self):
+        self.helper_primitives_2_params("value_eq", True, True, True)
+
+    def test_eq_T_F(self):
+        self.helper_primitives_2_params("value_eq", True, False, False)
+
+    def test_eq_F_T(self):
+        self.helper_primitives_2_params("value_eq", False, True, False)
+
+    def test_eq_F_F(self):
+        self.helper_primitives_2_params("value_eq", False, False, True)
+
+    def helper_primitives_2_params(self, operation, a, b, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CNV", [a])
+        self.value_second = self.mvs.execute("CNV", [b])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), result)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")
+
+    def helper_primitives_1_params(self, operation, a, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CNV", [a])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), result)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")
+

+ 196 - 0
kernel/test_generated/primitives/test_cast.py

@@ -0,0 +1,196 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces
+
+class TestCast(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_cast_float(self):
+        self.helper_primitives_1_params("cast_float", 2, 2.0)
+
+    def test_cast_string(self):
+        self.helper_primitives_1_params("cast_string", 2, "2")
+
+    def test_cast_boolean(self):
+        self.helper_primitives_1_params("cast_boolean", 2, True)
+
+    def test_cast_integer(self):
+        self.helper_primitives_1_params("cast_integer", 2.4, 2)
+
+    def test_cast_string(self):
+        self.helper_primitives_1_params("cast_string", 2.4, "2.4")
+
+    def test_cast_boolean(self):
+        self.helper_primitives_1_params("cast_boolean", 2.4, True)
+
+    def test_cast_integer(self):
+        self.helper_primitives_1_params("cast_integer", "2", 2)
+
+    def test_cast_float(self):
+        self.helper_primitives_1_params("cast_float", "2.4", 2.4)
+
+    def test_cast_boolean(self):
+        self.helper_primitives_1_params("cast_boolean", "2.4", True)
+
+    def test_cast_integer_true(self):
+        self.helper_primitives_1_params("cast_integer", True, 1)
+
+    def test_cast_float_true(self):
+        self.helper_primitives_1_params("cast_float", True, 1.0)
+
+    def test_cast_string_true(self):
+        self.helper_primitives_1_params("cast_string", True, "True")
+
+    def test_cast_integer_false(self):
+        self.helper_primitives_1_params("cast_integer", False, 0)
+
+    def test_cast_float_false(self):
+        self.helper_primitives_1_params("cast_float", False, 0.0)
+
+    def test_cast_string_false(self):
+        self.helper_primitives_1_params("cast_string", False, "False")
+
+    def test_cast_string_int(self):
+        n = self.mvs.execute("CN", [])
+        self.helper_primitives_1_params("cast_string", n, "None", t=True)
+
+    def test_cast_string_int(self):
+        self.helper_primitives_1_params("cast_string", 2, "2")
+
+    def test_cast_string_neg_int(self):
+        self.helper_primitives_1_params("cast_string", -2, "-2")
+
+    def test_cast_string_float(self):
+        self.helper_primitives_1_params("cast_string", 2.0, "2.0")
+
+    def test_cast_string_neg_float(self):
+        self.helper_primitives_1_params("cast_string", -2.0, "-2.0")
+
+    def test_cast_string_string(self):
+        self.helper_primitives_1_params("cast_string", "abc", "abc")
+
+    def test_cast_string_string_stringnum(self):
+        self.helper_primitives_1_params("cast_value", "3", "\"3\"")
+
+    def test_cast_string_string_num(self):
+        self.helper_primitives_1_params("cast_value", 3, "3")
+
+    def test_cast_string_bool(self):
+        self.helper_primitives_1_params("cast_value", True, "true")
+
+    def test_cast_string_action(self):
+        self.helper_primitives_1_params("cast_value", {"value": "call"}, "call")
+
+    def test_cast_id_node(self):
+        n = self.mvs.execute("CN", [])
+        self.helper_primitives_1_params("cast_id", n, str(n), t=True)
+
+    def test_cast_id_value(self):
+        n = self.mvs.execute("CNV", ["abc"])
+        self.helper_primitives_1_params("cast_id", n, str(n), t=True)
+
+    def test_cast_id_edge(self):
+        a = self.mvs.execute("CN", [])
+        b = self.mvs.execute("CN", [])
+        n = self.mvs.execute("CE", [a, b])
+        self.helper_primitives_1_params("cast_id", n, str(n), t=True)
+
+    def helper_primitives_1_params(self, operation, a, result, t=False):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        if t:
+            self.value_first = a
+        else:
+            self.value_first = self.mvs.execute("CNV", [a])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        if not t:
+            self.assertEquals(get_returnvalue(self.root, self.mvs), a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), result)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")

+ 258 - 0
kernel/test_generated/primitives/test_create.py

@@ -0,0 +1,258 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces, get_returnvalue_ref
+
+class TestCreate(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_create_node(self):
+        self.helper_primitives_no_params("create_node")
+        v = get_returnvalue_ref(self.root, self.mvs)
+        # v should be a newly created node that is unused at the moment
+        self.assertEquals(self.mvs.execute("RV", [v]), None)
+        self.assertEquals(self.mvs.execute("RE", [v]), [None, None])
+        self.assertEquals(len(self.mvs.execute("RO", [v])), 0)
+        # There is an incoming link, as this is due to the returnvalue link
+        self.assertEquals(len(self.mvs.execute("RI", [v])), 1)
+
+    def test_create_edge(self):
+        a = self.mvs.execute("CN", [])
+        b = self.mvs.execute("CN", [])
+        self.helper_primitives_2_params("create_edge", a, b)
+        v = get_returnvalue_ref(self.root, self.mvs)
+
+        # v should be a newly created edge that is unused at the moment
+        self.assertEquals(self.mvs.execute("RV", [v]), None)
+        self.assertEquals(self.mvs.execute("RE", [v]), [a, b])
+        self.assertEquals(len(self.mvs.execute("RO", [v])), 0)
+        # There is an incoming link, as this is due to the returnvalue link
+        self.assertEquals(len(self.mvs.execute("RI", [v])), 1)
+
+    def test_create_value(self):
+        v = self.mvs.execute("CNV", [1])
+        self.helper_primitives_1_params("create_value", v)
+
+        v = get_returnvalue_ref(self.root, self.mvs)
+        # v should be a newly created node that is unused at the moment
+        self.assertEquals(self.mvs.execute("RV", [v]), 1)
+        self.assertEquals(self.mvs.execute("RE", [v]), [None, None])
+        self.assertEquals(len(self.mvs.execute("RO", [v])), 0)
+        # There is an incoming link, as this is due to the returnvalue link
+        self.assertEquals(len(self.mvs.execute("RI", [v])), 1)
+
+    def helper_primitives_2_params(self, operation, a, b):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = a
+        self.value_second = b
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_second)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+    def helper_primitives_1_params(self, operation, a):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = a
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+
+    def helper_primitives_no_params(self, operation):
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")

+ 149 - 0
kernel/test_generated/primitives/test_delete.py

@@ -0,0 +1,149 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces, get_returnvalue_ref
+
+class TestDelete(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_delete_node(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [a, v])
+        self.helper_primitives_1_params("delete_element", v)
+
+        self.assertEquals(self.mvs.execute("RV", [v]), None)
+        self.assertEquals(self.mvs.execute("RE", [v]), [None, None])
+        self.assertEquals(self.mvs.execute("RO", [v]), None)
+        self.assertEquals(self.mvs.execute("RI", [v]), None)
+
+        # The edge is gone too
+        self.assertEquals(self.mvs.execute("RV", [e]), None)
+        self.assertEquals(self.mvs.execute("RE", [e]), [None, None])
+        self.assertEquals(self.mvs.execute("RO", [e]), None)
+        self.assertEquals(self.mvs.execute("RI", [e]), None)
+
+        # But the other node remains
+        self.assertEquals(self.mvs.execute("RV", [a]), None)
+        self.assertEquals(self.mvs.execute("RE", [a]), [None, None])
+        self.assertNotEquals(self.mvs.execute("RO", [a]), None)
+        self.assertNotEquals(self.mvs.execute("RI", [a]), None)
+
+        r = get_returnvalue(self.root, self.mvs)
+        self.assertEquals(r, False)
+
+    def test_delete_edge(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [a, v])
+        self.helper_primitives_1_params("delete_element", e)
+
+        # Edge disappears
+        self.assertEquals(self.mvs.execute("RV", [e]), None)
+        self.assertEquals(self.mvs.execute("RE", [e]), [None, None])
+        self.assertEquals(self.mvs.execute("RO", [e]), None)
+        self.assertEquals(self.mvs.execute("RI", [e]), None)
+
+        # But the nodes remains
+        self.assertEquals(self.mvs.execute("RV", [a]), None)
+        self.assertEquals(self.mvs.execute("RE", [a]), [None, None])
+        self.assertNotEquals(self.mvs.execute("RO", [a]), None)
+        self.assertNotEquals(self.mvs.execute("RI", [a]), None)
+
+        self.assertEquals(self.mvs.execute("RV", [v]), None)
+        self.assertEquals(self.mvs.execute("RE", [v]), [None, None])
+        self.assertNotEquals(self.mvs.execute("RO", [v]), None)
+        self.assertNotEquals(self.mvs.execute("RI", [v]), None)
+
+        r = get_returnvalue(self.root, self.mvs)
+        self.assertEquals(r, True)
+
+    def helper_primitives_1_params(self, operation, a):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = a
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.returnvalue)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.returnvalue)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.primitives[operation])
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.primitives[operation])
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")

+ 338 - 0
kernel/test_generated/primitives/test_dict.py

@@ -0,0 +1,338 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces, get_returnvalue_ref
+
+class TestDict(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_delete(self):
+        self.helper_primitives_2_params("dict_delete", {"a": 5}, "a", {})
+
+    def test_in(self):
+        self.helper_primitives_2_params("dict_in", {"a": 5}, "a", True)
+
+    def test_in_empty(self):
+        self.helper_primitives_2_params("dict_in", {}, "a", False)
+
+    def test_in_similar(self):
+        # This is inherited from Python: if the values are actually equal (e.g. 1.0 == 1 and 1 == True), they are also equal in reading from dictionaries
+        # This is actually rather helpful, despite being counter-intuitive, since otherwise we might mix up with casts between unicode and string, for example
+        self.helper_primitives_2_params("dict_in", {1.0: 2}, 1, True)
+
+    def test_in_value(self):
+        self.helper_primitives_2_params("dict_in", {1: 2}, 1, True)
+
+    def test_in_mixed(self):
+        self.helper_primitives_2_params("dict_in", {2: "b", "a": 1, False: False}, 1, False)
+
+    def test_in_mixed_true(self):
+        self.helper_primitives_2_params("dict_in", {2: "b", "a": 1, False: False}, False, True)
+
+    def test_delete_multi(self):
+        self.helper_primitives_2_params("dict_delete", {"a": 5, "b": 6}, "a", {"b": 6})
+
+    def test_read(self):
+        self.helper_primitives_2_params("dict_read", {"a": 5, "b": 6}, "a", 5)
+
+    def construct(self, source, dct):
+        for i, v in dct.items():
+            t = self.mvs.execute("CNV", [v])
+            self.mvs.execute("CD", [source, i, t])
+
+    def parse(self, source, expected):
+        if isinstance(expected, dict):
+            self.assertEquals(len(self.mvs.execute("RO", [source])), len(expected))
+            for i, v in expected.items():
+                self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [source, i])]), v)
+        else:
+            self.assertEquals(get_returnvalue(self.root, self.mvs), expected)
+
+    def helper_primitives_2_params(self, operation, a, b, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CN", [])
+        self.value_second = self.mvs.execute("CNV", [b])
+
+        self.construct(self.value_first, a)
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+
+        self.parse(self.value_first, result)
+
+    def helper_primitives_1_params(self, operation, a, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+
+        self.construct(self.value_first, a)
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.parse(self.value_first, result)
+
+    def helper_primitives_3_params(self, operation, a, b, c, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+        self.actual_arg_c = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_third = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CN", [])
+        self.value_second = self.mvs.execute("CNV", [b])
+        self.value_third = self.mvs.execute("CNV", [c])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_b, "next_param", self.actual_arg_c])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_c])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_c, "value", self.const_third])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.actual_arg_c, "name", self.value_c])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+        self.mvs.execute("CD", [self.const_third, "node", self.value_third])
+
+        self.construct(self.value_first, a)
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_c)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), c)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+
+        self.parse(self.value_first, result)

+ 255 - 0
kernel/test_generated/primitives/test_dict_special.py

@@ -0,0 +1,255 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces, get_returnvalue_ref
+
+class TestDictSpecials(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_read_edge(self):
+        n = self.mvs.execute("CN", [])
+        v_a = self.mvs.execute("CN", [])
+        k_a = self.mvs.execute("CNV", ["a"])
+        edge = self.mvs.execute("CE", [n, v_a])
+        self.mvs.execute("CE", [edge, k_a])
+        self.helper_primitives_2_params("dict_read_edge", n, self.mvs.execute("CNV", ["a"]), edge)
+
+    def test_read_node(self):
+        n = self.mvs.execute("CN", [])
+        v_a = self.mvs.execute("CN", [])
+        k_a = self.mvs.execute("CN", [])
+        edge = self.mvs.execute("CE", [n, v_a])
+        self.mvs.execute("CE", [edge, k_a])
+        self.helper_primitives_2_params("dict_read_node", n, k_a, v_a)
+
+    def test_in_node(self):
+        n = self.mvs.execute("CN", [])
+        v_a = self.mvs.execute("CN", [])
+        k_a = self.mvs.execute("CN", [])
+        edge = self.mvs.execute("CE", [n, v_a])
+        self.mvs.execute("CE", [edge, k_a])
+        self.helper_primitives_2_params("dict_in_node", n, k_a, True, is_val=True)
+
+    def test_in_node_false(self):
+        n = self.mvs.execute("CN", [])
+        v_a = self.mvs.execute("CN", [])
+        k_a = self.mvs.execute("CN", [])
+        k_a2 = self.mvs.execute("CN", [])
+        edge = self.mvs.execute("CE", [n, v_a])
+        self.mvs.execute("CE", [edge, k_a])
+        self.helper_primitives_2_params("dict_in_node", n, k_a2, False, is_val=True)
+
+    def test_in_node_true(self):
+        n = self.mvs.execute("CN", [])
+        v_a = self.mvs.execute("CN", [])
+        k_a = self.mvs.execute("CN", [])
+        edge = self.mvs.execute("CE", [n, v_a])
+        self.mvs.execute("CE", [edge, k_a])
+        self.helper_primitives_2_params("dict_in_node", n, k_a, True, is_val=True)
+
+    def test_read_node_value(self):
+        n = self.mvs.execute("CN", [])
+        v_a = self.mvs.execute("CN", [])
+        k_a = self.mvs.execute("CNV", [1])
+        edge = self.mvs.execute("CE", [n, v_a])
+        self.mvs.execute("CE", [edge, k_a])
+        self.helper_primitives_2_params("dict_read_node", n, self.mvs.execute("CNV", [1]), None)
+
+    def test_keys(self):
+        n = self.mvs.execute("CN", [])
+        self.mvs.execute("CD", [n, "abc", self.mvs.execute("CNV", [1])])
+        self.mvs.execute("CD", [n, "d", self.mvs.execute("CNV", ["a"])])
+        self.mvs.execute("CD", [n, "123", self.mvs.execute("CNV", [True])])
+        self.helper_primitives_1_params("dict_keys", n, ["abc", "d", "123"])
+
+    def parse(self, source, expected):
+        if isinstance(expected, dict):
+            self.assertEquals(len(self.mvs.execute("RO", [source])), len(expected))
+            for i, v in expected.items():
+                self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [source, i])]), v)
+        else:
+            self.assertEquals(get_returnvalue(self.root, self.mvs), expected)
+
+    def helper_primitives_2_params(self, operation, a, b, result, is_val=False):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+
+        self.value_first = a
+        self.value_second = b
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        
+        if not is_val:
+            self.assertEquals(get_returnvalue_ref(self.root, self.mvs), result)
+        else:
+            self.assertEquals(get_returnvalue(self.root, self.mvs), result)
+
+    def helper_primitives_1_params(self, operation, a, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+
+        self.value_first = a
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        
+        returnval = get_returnvalue_ref(self.root, self.mvs)
+        outgoing_links = self.mvs.execute("RO", [returnval])
+        received = []
+        for l in outgoing_links:
+            outgoing_links_2 = self.mvs.execute("RO", [l])
+            src, dst = self.mvs.execute("RE", [outgoing_links_2[0]])
+            received.append(self.mvs.execute("RV", [dst]))
+
+        self.assertEquals(sorted(received), sorted(result))

+ 108 - 0
kernel/test_generated/primitives/test_edge.py

@@ -0,0 +1,108 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces, get_returnvalue_ref
+
+class TestEdge(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_is_edge_N(self):
+        a = self.mvs.execute("CN", [])
+        self.helper_primitives_1_params("is_edge", a, False)
+
+    def test_is_edge_V(self):
+        a = self.mvs.execute("CNV", [5])
+        self.helper_primitives_1_params("is_edge", a, False)
+
+    def test_is_edge_E(self):
+        a = self.mvs.execute("CN", [])
+        b = self.mvs.execute("CN", [])
+        c = self.mvs.execute("CE", [a, b])
+        self.helper_primitives_1_params("is_edge", c, True)
+
+    def helper_primitives_1_params(self, operation, a, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = a
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+
+        self.assertEquals(get_returnvalue(self.root, self.mvs), result)

+ 138 - 0
kernel/test_generated/primitives/test_element.py

@@ -0,0 +1,138 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces
+
+class TestType(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_eq_true_value(self):
+        a = self.mvs.execute("CNV", [5])
+        self.helper_primitives_2_params("element_eq", a, a, True)
+
+    def test_eq_true_novalue(self):
+        a = self.mvs.execute("CN", [])
+        self.helper_primitives_2_params("element_eq", a, a, True)
+
+    def test_eq_false_value(self):
+        a = self.mvs.execute("CNV", [5])
+        b = self.mvs.execute("CNV", [5])
+        self.helper_primitives_2_params("element_eq", a, b, False)
+
+    def test_eq_false_novalue(self):
+        a = self.mvs.execute("CN", [])
+        b = self.mvs.execute("CN", [])
+        self.helper_primitives_2_params("element_eq", a, b, False)
+
+    def helper_primitives_2_params(self, operation, a, b, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = a
+        self.value_second = b
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), result)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")

+ 225 - 0
kernel/test_generated/primitives/test_float.py

@@ -0,0 +1,225 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces
+
+class TestInteger(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_addition(self):
+        self.helper_primitives_2_params("float_addition", 2.4, 5.8, 8.2)
+
+    def test_subtraction(self):
+        self.helper_primitives_2_params("float_subtraction", 2.4, 5.8, -3.4)
+
+    def test_multiplication(self):
+        self.helper_primitives_2_params("float_multiplication", 2.4, 5.8, 13.92)
+
+    def test_division(self):
+        self.helper_primitives_2_params("float_division", 5.8, 2.4, 5.8/2.4)
+
+    def test_lt_less(self):
+        self.helper_primitives_2_params("float_lt", 2.4, 5.8, True)
+
+    def test_lt_eq(self):
+        self.helper_primitives_2_params("float_lt", 2.4, 2.4, False)
+
+    def test_lt_greater(self):
+        self.helper_primitives_2_params("float_lt", 5.8, 2.4, False)
+
+    def test_eq_diff(self):
+        self.helper_primitives_2_params("value_eq", 2.4, 5.8, False)
+
+    def test_eq_eq(self):
+        self.helper_primitives_2_params("value_eq", 2.4, 2.4, True)
+
+    def helper_primitives_2_params(self, operation, a, b, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CNV", [a])
+        self.value_second = self.mvs.execute("CNV", [b])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), result)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")
+
+    def helper_primitives_1_params(self, operation, a, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CNV", [a])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), result)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")

+ 225 - 0
kernel/test_generated/primitives/test_integer.py

@@ -0,0 +1,225 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces
+
+class TestInteger(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_addition(self):
+        self.helper_primitives_2_params("integer_addition", 2, 5, 7)
+
+    def test_subtraction(self):
+        self.helper_primitives_2_params("integer_subtraction", 2, 5, -3)
+
+    def test_multiplication(self):
+        self.helper_primitives_2_params("integer_multiplication", 2, 5, 10)
+
+    def test_division(self):
+        self.helper_primitives_2_params("integer_division", 5, 2, 2)
+
+    def test_lt_less(self):
+        self.helper_primitives_2_params("integer_lt", 2, 5, True)
+
+    def test_lt_eq(self):
+        self.helper_primitives_2_params("integer_lt", 2, 2, False)
+
+    def test_lt_greater(self):
+        self.helper_primitives_2_params("integer_lt", 5, 2, False)
+
+    def test_eq_diff(self):
+        self.helper_primitives_2_params("value_eq", 2, 5, False)
+
+    def test_eq_eq(self):
+        self.helper_primitives_2_params("value_eq", 2, 2, True)
+
+    def helper_primitives_2_params(self, operation, a, b, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CNV", [a])
+        self.value_second = self.mvs.execute("CNV", [b])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), result)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")
+
+    def helper_primitives_1_params(self, operation, a, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CNV", [a])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), result)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")

+ 327 - 0
kernel/test_generated/primitives/test_list.py

@@ -0,0 +1,327 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces, get_returnvalue_ref
+
+class TestList(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_insert_front(self):
+        self.helper_primitives_3_params("list_insert", ["b", "c", "d"], "a", 0, ["a", "b", "c", "d"])
+
+    def test_insert_back(self):
+        self.helper_primitives_3_params("list_insert", ["b", "c", "d"], "e", 3, ["b", "c", "d", "e"])
+
+    def test_insert(self):
+        self.helper_primitives_3_params("list_insert", ["b", "d", "f"], "c", 1, ["b", "c", "d", "f"])
+
+    def test_delete_front(self):
+        self.helper_primitives_2_params("list_delete", ["b", "c", "d"], 0, ["c", "d"])
+
+    def test_delete_back(self):
+        self.helper_primitives_2_params("list_delete", ["b", "c", "d"], 2, ["b", "c"])
+
+    def test_delete(self):
+        self.helper_primitives_2_params("list_delete", ["b", "d", "f"], 1, ["b", "f"])
+
+    def construct(self, source, lst):
+        for i, v in enumerate(lst):
+            t = self.mvs.execute("CNV", [v])
+            self.mvs.execute("CD", [source, i, t])
+
+    def parse(self, source, expected):
+        if isinstance(expected, list):
+            self.assertEquals(len(self.mvs.execute("RO", [source])), len(expected))
+            for i, v in enumerate(expected):
+                self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [source, i])]), v)
+        else:
+            self.assertEquals(get_returnvalue(self.root, self.mvs), expected)
+
+    def helper_primitives_2_params(self, operation, a, b, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CN", [])
+        self.value_second = self.mvs.execute("CNV", [b])
+
+        self.construct(self.value_first, a)
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.parse(self.value_first, result)
+
+    def helper_primitives_1_params(self, operation, a, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+
+        self.construct(self.value_first, a)
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+
+        self.parse(self.value_first, result)
+
+    def helper_primitives_3_params(self, operation, a, b, c, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+        self.actual_arg_c = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_third = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CN", [])
+        self.value_second = self.mvs.execute("CNV", [b])
+        self.value_third = self.mvs.execute("CNV", [c])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_b, "next_param", self.actual_arg_c])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_c])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_c, "value", self.const_third])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.actual_arg_c, "name", self.value_c])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+        self.mvs.execute("CD", [self.const_third, "node", self.value_third])
+
+        self.construct(self.value_first, a)
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_c)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), c)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+
+        self.parse(self.value_first, result)

+ 386 - 0
kernel/test_generated/primitives/test_read.py

@@ -0,0 +1,386 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces, get_returnvalue_ref
+
+class TestRead(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_read_root(self):
+        self.helper_primitives_no_params("read_root")
+        v = get_returnvalue_ref(self.root, self.mvs)
+        self.assertEquals(v, self.root)
+
+    def test_read_nr_out_none(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [a, v])
+        self.helper_primitives_1_params("read_nr_out", v)
+
+        v = get_returnvalue_ref(self.root, self.mvs)
+        self.assertEquals(self.mvs.execute("RV", [v]), 0)
+        self.assertEquals(self.mvs.execute("RE", [v]), [None, None])
+        self.assertEquals(len(self.mvs.execute("RO", [v])), 0)
+        # There is an incoming link, as this is due to the returnvalue link
+        self.assertEquals(len(self.mvs.execute("RI", [v])), 1)
+
+    def test_read_nr_out_one(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [v, a])
+        self.helper_primitives_1_params("read_nr_out", v)
+
+        v = get_returnvalue_ref(self.root, self.mvs)
+        self.assertEquals(self.mvs.execute("RV", [v]), 1)
+        self.assertEquals(self.mvs.execute("RE", [v]), [None, None])
+        self.assertEquals(len(self.mvs.execute("RO", [v])), 0)
+        # There is an incoming link, as this is due to the returnvalue link
+        self.assertEquals(len(self.mvs.execute("RI", [v])), 1)
+
+    def test_read_nr_out_multi(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [v, a])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [v, a])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [v, a])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [v, a])
+        self.helper_primitives_1_params("read_nr_out", v)
+
+        v = get_returnvalue_ref(self.root, self.mvs)
+        self.assertEquals(self.mvs.execute("RV", [v]), 4)
+        self.assertEquals(self.mvs.execute("RE", [v]), [None, None])
+        self.assertEquals(len(self.mvs.execute("RO", [v])), 0)
+        # There is an incoming link, as this is due to the returnvalue link
+        self.assertEquals(len(self.mvs.execute("RI", [v])), 1)
+
+    def test_read_nr_in_none(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [v, a])
+        self.helper_primitives_1_params("read_nr_in", v)
+
+        v = get_returnvalue_ref(self.root, self.mvs)
+        # There are still input links from the execution itself, such as entries in symbol table, parameter lists, ...
+        self.assertEquals(self.mvs.execute("RV", [v]), 3)
+        self.assertEquals(self.mvs.execute("RE", [v]), [None, None])
+        self.assertEquals(len(self.mvs.execute("RO", [v])), 0)
+        # There is an incoming link, as this is due to the returnvalue link
+        self.assertEquals(len(self.mvs.execute("RI", [v])), 1)
+
+    def test_read_nr_in_one(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [a, v])
+        self.helper_primitives_1_params("read_nr_in", v)
+
+        v = get_returnvalue_ref(self.root, self.mvs)
+        # There are still input links from the execution itself, such as entries in symbol table, parameter lists, ...
+        self.assertEquals(self.mvs.execute("RV", [v]), 4)
+        self.assertEquals(self.mvs.execute("RE", [v]), [None, None])
+        self.assertEquals(len(self.mvs.execute("RO", [v])), 0)
+        # There is an incoming link, as this is due to the returnvalue link
+        self.assertEquals(len(self.mvs.execute("RI", [v])), 1)
+
+    def test_read_nr_in_multi(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [a, v])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [a, v])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [a, v])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [a, v])
+        self.helper_primitives_1_params("read_nr_in", v)
+
+        v = get_returnvalue_ref(self.root, self.mvs)
+        # There are still input links from the execution itself, such as entries in symbol table, parameter lists, ...
+        self.assertEquals(self.mvs.execute("RV", [v]), 7)
+        self.assertEquals(self.mvs.execute("RE", [v]), [None, None])
+        self.assertEquals(len(self.mvs.execute("RO", [v])), 0)
+        # There is an incoming link, as this is due to the returnvalue link
+        self.assertEquals(len(self.mvs.execute("RI", [v])), 1)
+
+    def test_read_out_one(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [v, a])
+        self.helper_primitives_2_params("read_out", v, self.mvs.execute("CNV", [0]))
+
+        v = get_returnvalue_ref(self.root, self.mvs)
+        self.assertEquals(v, e)
+
+    def test_read_out_multi(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e1 = self.mvs.execute("CE", [v, a])
+        a = self.mvs.execute("CN", [])
+        e2 = self.mvs.execute("CE", [v, a])
+        a = self.mvs.execute("CN", [])
+        e3 = self.mvs.execute("CE", [v, a])
+        a = self.mvs.execute("CN", [])
+        e4 = self.mvs.execute("CE", [v, a])
+        self.helper_primitives_2_params("read_out", v, self.mvs.execute("CNV", [2]))
+
+        v = get_returnvalue_ref(self.root, self.mvs)
+        self.assertEquals(v, e3)
+
+    def test_read_in_one(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [a, v])
+        self.helper_primitives_2_params("read_in", v, self.mvs.execute("CNV", [0]))
+
+        v = get_returnvalue_ref(self.root, self.mvs)
+        self.assertEquals(v, e)
+
+    def test_read_in_multi(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e1 = self.mvs.execute("CE", [a, v])
+        a = self.mvs.execute("CN", [])
+        e2 = self.mvs.execute("CE", [a, v])
+        a = self.mvs.execute("CN", [])
+        e3 = self.mvs.execute("CE", [a, v])
+        a = self.mvs.execute("CN", [])
+        e4 = self.mvs.execute("CE", [a, v])
+        self.helper_primitives_2_params("read_in", v, self.mvs.execute("CNV", [2]))
+
+        v = get_returnvalue_ref(self.root, self.mvs)
+        self.assertEquals(v, e3)
+
+    def test_read_edge_src(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [a, v])
+        self.helper_primitives_1_params("read_edge_src", e)
+
+        r = get_returnvalue_ref(self.root, self.mvs)
+        self.assertEquals(r, a)
+
+    def test_read_edge_dst(self):
+        v = self.mvs.execute("CN", [])
+        a = self.mvs.execute("CN", [])
+        e = self.mvs.execute("CE", [a, v])
+        self.helper_primitives_1_params("read_edge_dst", e)
+
+        r = get_returnvalue_ref(self.root, self.mvs)
+        self.assertEquals(r, v)
+
+    def helper_primitives_2_params(self, operation, a, b):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = a
+        self.value_second = b
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_second)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+
+    def helper_primitives_1_params(self, operation, a):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = a
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue_ref(self.root, self.mvs), self.value_first)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+
+    def helper_primitives_no_params(self, operation, expected=None):
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")

+ 367 - 0
kernel/test_generated/primitives/test_string.py

@@ -0,0 +1,367 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper, get_inst, get_phase, get_returnvalue, get_phase_ref, read_primitive_interfaces, get_returnvalue_ref
+
+class TestString(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+        self.task_root = self.mvs.execute("CN", [])
+        self.task_frame = self.mvs.execute("CN", [])
+        self.symbols = self.mvs.execute("CN", [])
+        self.evalstack = self.mvs.execute("CN", [])
+        self.returnvalue = self.mvs.execute("CN", [])
+        self.phase = self.mvs.execute("CNV", ["init"])
+
+        self.mvs.execute("CD", [self.root, "task_1", self.task_root])
+        self.mvs.execute("CD", [self.task_root, "frame", self.task_frame])
+        self.mvs.execute("CD", [self.task_frame, "symbols", self.symbols])
+        self.mvs.execute("CD", [self.task_frame, "evalstack", self.evalstack])
+        self.mvs.execute("CD", [self.task_frame, "phase", self.phase])
+        self.mvs.execute("CD", [self.task_frame, "returnvalue", self.returnvalue])
+
+        execute_until_finished(self.mvk, self.mvs, "load_primitives", [])
+        self.primitives = read_primitive_interfaces(self.root, self.mvs)
+
+    def test_eq(self):
+        self.helper_primitives_2_params("value_eq", "abc", "abc", True)
+
+    def test_eq_startswith(self):
+        self.helper_primitives_2_params("value_eq", "abc", "abcdef", False)
+
+    def test_eq_samelength(self):
+        self.helper_primitives_2_params("value_eq", "abc", "def", False)
+
+    def test_eq_diff(self):
+        self.helper_primitives_2_params("value_eq", "abc", "defghij", False)
+
+    def test_eq_empty(self):
+        self.helper_primitives_2_params("value_eq", "", "", True)
+
+    def test_join(self):
+        self.helper_primitives_2_params("string_join", "abc", "def", "abcdef")
+
+    def test_join_empty_left(self):
+        self.helper_primitives_2_params("string_join", "", "def", "def")
+
+    def test_join_empty_right(self):
+        self.helper_primitives_2_params("string_join", "abc", "", "abc")
+
+    def test_join_empty_both(self):
+        self.helper_primitives_2_params("string_join", "", "", "")
+
+    def test_get_first(self):
+        self.helper_primitives_2_params("string_get", "abcdefghijklmnopqrstuvwxyz", 0, "a")
+
+    def test_get_last(self):
+        self.helper_primitives_2_params("string_get", "abcdefghijklmnopqrstuvwxyz", 25, "z")
+
+    def test_len(self):
+        self.helper_primitives_1_params("string_len", "abcdefghijklmnopqrstuvwxyz", 26)
+
+    def test_len_empty(self):
+        self.helper_primitives_1_params("string_len", "", 0)
+
+    def test_split(self):
+        self.helper_primitives_2_params("string_split", "abc;defg;hij", ";", ["abc", "defg", "hij"])
+
+    def test_split_single(self):
+        self.helper_primitives_2_params("string_split", "abc;defg;hij", "/", ["abc;defg;hij"])
+
+    def test_split_withempty(self):
+        self.helper_primitives_2_params("string_split", "abc;defg;;hij", ";", ["abc", "defg", "", "hij"])
+
+    def helper_primitives_2_params(self, operation, a, b, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CNV", [a])
+        self.value_second = self.mvs.execute("CNV", [b])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        if isinstance(result, list):
+            ref = get_returnvalue_ref(self.root, self.mvs)
+            for i, v in enumerate(result):
+                self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [ref, i])]), v)
+        else:
+            self.assertEquals(get_returnvalue(self.root, self.mvs), result)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")
+
+    def helper_primitives_1_params(self, operation, a, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CNV", [a])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), result)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")
+
+    def helper_primitives_3_params(self, operation, a, b, c, result):
+        self.actual_arg_a = self.mvs.execute("CN", [])
+        self.actual_arg_b = self.mvs.execute("CN", [])
+        self.actual_arg_c = self.mvs.execute("CN", [])
+
+        self.inst = self.mvs.execute("CNV", [{"value":"call"}])
+        self.const_a = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_b = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_c = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_first = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_second = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.const_third = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.value_a = self.mvs.execute("CNV", ["a"])
+        self.value_b = self.mvs.execute("CNV", ["b"])
+        self.value_c = self.mvs.execute("CNV", ["c"])
+        self.value_first = self.mvs.execute("CNV", [a])
+        self.value_second = self.mvs.execute("CNV", [b])
+        self.value_third = self.mvs.execute("CNV", [c])
+
+        self.mvs.execute("CD", [self.task_frame, "IP", self.inst])
+        self.const_func = self.mvs.execute("CNV", [{"value":"constant"}])
+        self.mvs.execute("CD", [self.inst, "func", self.const_func])
+        self.mvs.execute("CD", [self.const_func, "node", self.primitives[operation]])
+        self.mvs.execute("CD", [self.inst, "next", self.const_c])
+        self.mvs.execute("CD", [self.inst, "params", self.actual_arg_a])
+        self.mvs.execute("CD", [self.actual_arg_a, "next_param", self.actual_arg_b])
+        self.mvs.execute("CD", [self.actual_arg_b, "next_param", self.actual_arg_c])
+        self.mvs.execute("CD", [self.inst, "last_param", self.actual_arg_c])
+        self.mvs.execute("CD", [self.actual_arg_a, "value", self.const_first])
+        self.mvs.execute("CD", [self.actual_arg_b, "value", self.const_second])
+        self.mvs.execute("CD", [self.actual_arg_c, "value", self.const_third])
+        self.mvs.execute("CD", [self.actual_arg_a, "name", self.value_a])
+        self.mvs.execute("CD", [self.actual_arg_b, "name", self.value_b])
+        self.mvs.execute("CD", [self.actual_arg_c, "name", self.value_c])
+        self.mvs.execute("CD", [self.const_a, "node", self.value_a])
+        self.mvs.execute("CD", [self.const_b, "node", self.value_b])
+        self.mvs.execute("CD", [self.const_c, "node", self.value_c])
+        self.mvs.execute("CD", [self.const_first, "node", self.value_first])
+        self.mvs.execute("CD", [self.const_second, "node", self.value_second])
+        self.mvs.execute("CD", [self.const_third, "node", self.value_third])
+
+        ### Execute rules
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), a)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), b)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase_ref(self.root, self.mvs), self.actual_arg_c)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), c)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "call")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Body points to empty instruction, as it is a primitive
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        # This will have triggered the primitive, so now we are back where we left off
+        # Just check whether or not the correct value is in the returnvalue to be used
+        self.assertEquals(get_inst(self.root, self.mvs), "call")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), result)
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "init")
+        execute_until_finished(self.mvk, self.mvs)
+
+        self.assertEquals(get_inst(self.root, self.mvs), "constant")
+        self.assertEquals(get_phase(self.root, self.mvs), "finish")
+        self.assertEquals(get_returnvalue(self.root, self.mvs), "c")

+ 120 - 0
kernel/test_generated/primitives/utils.py

@@ -0,0 +1,120 @@
+import sys
+sys.path.append("../state")
+from modelverse_state.main import ModelverseState
+import json
+
+class MvSWrapper(object):
+    def __init__(self):
+        self.mvs = ModelverseState("../bootstrap/minimal.m.gz")
+
+        self.mapping = {
+                   "RD": self.mvs.read_dict,
+                   "RR": self.mvs.read_root,
+                   "RO": self.mvs.read_outgoing,
+                   "RI": self.mvs.read_incoming,
+                   "RE": self.mvs.read_edge,
+                   "RDE": self.mvs.read_dict_edge,
+                   "RDK": self.mvs.read_dict_keys,
+                   "RDN": self.mvs.read_dict_node,
+                   "RDNE": self.mvs.read_dict_node_edge,
+                   "RRD": self.mvs.read_reverse_dict,
+                   "RV": self.mvs.read_value,
+                   "CN": self.mvs.create_node,
+                   "CNV": self.mvs.create_nodevalue,
+                   "CE": self.mvs.create_edge,
+                   "DE": self.mvs.delete_edge,
+                   "DN": self.mvs.delete_node,
+                   "CD": self.mvs.create_dict,
+                  }
+
+    def execute(self, command, params):
+        params = json.loads(json.dumps(params))
+        retval = self.mapping[command](*params)
+        retval = json.loads(json.dumps(retval))
+
+        return retval
+
+def add_new_task(root, mvs, taskname):
+    hierarchy = mvs.execute("RD", [root, "__hierarchy"])
+    initial = mvs.execute("RD", [hierarchy, "__IP"])
+
+    task_root = mvs.execute("CN", [])
+    _globals = mvs.execute("CN", [])
+    frame = mvs.execute("CN", [])
+    evalstack = mvs.execute("CN", [])
+    symbols = mvs.execute("CN", [])
+    _input = mvs.execute("CN", [])
+    _output = mvs.execute("CN", [])
+    returnvalue = mvs.execute("CN", [])
+    phase = mvs.execute("CNV", ["init"])
+
+    mvs.execute("CD", [root, taskname, task_root])
+    mvs.execute("CD", [task_root, "frame", frame])
+    mvs.execute("CD", [task_root, "globals", _globals])
+    mvs.execute("CD", [task_root, "input", _input])
+    mvs.execute("CD", [task_root, "last_input", _input])
+    mvs.execute("CD", [task_root, "output", _output])
+    mvs.execute("CD", [task_root, "last_output", _output])
+    mvs.execute("CD", [frame, "evalstack", evalstack])
+    mvs.execute("CD", [frame, "returnvalue", returnvalue])
+    mvs.execute("CD", [frame, "phase", phase])
+    mvs.execute("CD", [frame, "IP", initial])
+    mvs.execute("CD", [frame, "symbols", symbols])
+
+def execute_until_finished(mvk, mvs, operation="execute_rule", params=[]):
+    taskname = "task_1"
+    if operation == "initialize_new_task":
+        return add_new_task(mvk.root, mvs, taskname)
+    response = None
+    while 1:
+        mvs_commands = mvk.execute_yields(taskname, operation, params, response)
+        if mvs_commands is None:
+            break
+        response = []
+        for command, param in mvs_commands:
+            response.append(mvs.execute(command, param))
+
+def get_inst(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    inst = mvs.execute("RD", [task_frame, "IP"])
+    return mvs.execute("RV", [inst])["value"]
+
+def get_phase(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    phase = mvs.execute("RD", [task_frame, "phase"])
+    return mvs.execute("RV", [phase])
+
+def get_returnvalue(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    returnvalue = mvs.execute("RD", [task_frame, "returnvalue"])
+    return mvs.execute("RV", [returnvalue])
+
+def get_inst_ref(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    return mvs.execute("RD", [task_frame, "IP"])
+
+def get_returnvalue_ref(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    return mvs.execute("RD", [task_frame, "returnvalue"])
+
+def get_phase_ref(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    phase = mvs.execute("RD", [task_frame, "phase"])
+    return phase
+
+def read_primitive_interfaces(root, mvs):
+    hierarchy = mvs.execute("RD", [root, "__hierarchy"])
+    primitives = mvs.execute("RD", [hierarchy, "primitives"])
+    keys = mvs.execute("RDK", [primitives])
+    d = {}
+    for k in keys:
+        value = mvs.execute("RDN", [primitives, k])
+        name = mvs.execute("RV", [k])
+        d[name] = value
+    return d

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


+ 65 - 0
kernel/test_generated/rules/test_rules_access.py

@@ -0,0 +1,65 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper
+
+class Testaccess(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+    def test_access_init(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"access"}])
+        evalstack = self.mvs.execute("CN", [])
+        var_inst = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+        self.mvs.execute("CD", [inst, "var", var_inst])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), var_inst)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [evalstack, "phase"])]), "eval")
+
+    def test_access_eval(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["eval"])
+        inst = self.mvs.execute("CNV", [{"value":"access"}])
+        value = self.mvs.execute("CN", [])
+        returnvalue = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [returnvalue, "value", value])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "returnvalue"]), value)

+ 105 - 0
kernel/test_generated/rules/test_rules_assign.py

@@ -0,0 +1,105 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper
+
+class TestAssign(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+    def test_assign_init(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"assign"}])
+        evalstack = self.mvs.execute("CN", [])
+        var_inst = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+        self.mvs.execute("CD", [inst, "var", var_inst])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), var_inst)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [evalstack, "phase"])]), "value")
+
+    def test_assign_value(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["value"])
+        inst = self.mvs.execute("CNV", [{"value":"assign"}])
+        evalstack = self.mvs.execute("CN", [])
+        returnvalue = self.mvs.execute("CN", [])
+        value_inst = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+        self.mvs.execute("CD", [inst, "value", value_inst])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), value_inst)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "returnvalue"]), returnvalue)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "variable"]), returnvalue)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [evalstack, "phase"])]), "assign")
+
+    def test_assign_assign(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["assign"])
+        inst = self.mvs.execute("CNV", [{"value":"assign"}])
+        evalstack = self.mvs.execute("CN", [])
+        returnvalue = self.mvs.execute("CN", [])
+        variable = self.mvs.execute("CN", [])
+        value_inst = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+        self.mvs.execute("CD", [task_frame, "variable", variable])
+        self.mvs.execute("CD", [variable, "value", value_inst])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "variable"]), None)
+        self.assertEquals(self.mvs.execute("RD", [variable, "value"]), returnvalue)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "returnvalue"]), returnvalue)

+ 43 - 0
kernel/test_generated/rules/test_rules_break.py

@@ -0,0 +1,43 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper
+
+class Testbreak(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+    def test_basic(self):
+        # Create a break construct
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"break"}])
+        while_inst = self.mvs.execute("CNV", ["while"])
+        evalstack_top = self.mvs.execute("CN", [])
+        evalstack_bottom = self.mvs.execute("CN", [])
+        finish_phase = self.mvs.execute("CNV", ["finish"])
+
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack_top])
+        self.mvs.execute("CD", [evalstack_top, "prev", evalstack_bottom])
+        self.mvs.execute("CD", [evalstack_bottom, "inst", while_inst])
+        self.mvs.execute("CD", [evalstack_bottom, "task_1", while_inst])
+        self.mvs.execute("CD", [evalstack_bottom, "phase", finish_phase])
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [inst, "while", while_inst])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [inst, "while"]), while_inst)
+        self.assertNotEquals(self.mvs.execute("RD", [task_frame, "evalstack"]), evalstack_top)

+ 397 - 0
kernel/test_generated/rules/test_rules_call.py

@@ -0,0 +1,397 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper
+
+class Testcall(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+    def test_call_resolve_none(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"call"}])
+        evalstack = self.mvs.execute("CN", [])
+        func = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "symbols", self.mvs.execute("CN", [])])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [inst, "func", func])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), func)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [evalstack, "phase"])]), "call")
+
+    def test_call_resolve_params(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"call"}])
+        evalstack = self.mvs.execute("CN", [])
+        func = self.mvs.execute("CN", [])
+        params = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "symbols", self.mvs.execute("CN", [])])
+        self.mvs.execute("CD", [inst, "func", func])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+        self.mvs.execute("CD", [inst, "params", params])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), func)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "phase"]), params)
+
+    def test_call_execute_none(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["call"])
+        inst = self.mvs.execute("CNV", [{"value":"call"}])
+        returnvalue = self.mvs.execute("CN", [])
+        body = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "symbols", self.mvs.execute("CN", [])])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+        self.mvs.execute("CD", [returnvalue, "body", body])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)
+        new_frame = self.mvs.execute("RD", [task_root, "frame"])
+        self.assertNotEquals(new_frame, None)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), new_frame)
+        new_evalstack = self.mvs.execute("RD", [new_frame, "evalstack"])
+        self.assertNotEquals(new_evalstack, None)
+        new_symbols = self.mvs.execute("RD", [new_frame, "symbols"])
+        self.assertNotEquals(new_symbols, None)
+        new_returnvalue = self.mvs.execute("RD", [new_frame, "returnvalue"])
+        self.assertNotEquals(new_returnvalue, None)
+        new_caller = self.mvs.execute("RD", [new_frame, "caller"])
+        self.assertNotEquals(new_caller, None)
+        new_phase = self.mvs.execute("RD", [new_frame, "phase"])
+        self.assertNotEquals(new_phase, None)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [new_frame, "phase"])]), "init")
+        new_IP = self.mvs.execute("RD", [new_frame, "IP"])
+        self.assertNotEquals(new_IP, None)
+        self.assertEquals(self.mvs.execute("RD", [new_frame, "IP"]), body)
+        self.assertEquals(self.mvs.execute("RD", [new_frame, "caller"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [new_frame, "prev"]), task_frame)
+
+    def test_call_execute_params(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["call"])
+        inst = self.mvs.execute("CNV", [{"value":"call"}])
+        returnvalue = self.mvs.execute("CN", [])
+        body = self.mvs.execute("CN", [])
+        new_frame = self.mvs.execute("CN", [])
+        symbols = self.mvs.execute("CN", [])
+        signature = self.mvs.execute("CN", [])
+        params = self.mvs.execute("CN", [])
+        name = self.mvs.execute("CNV", ["param_a"])
+        last_param = self.mvs.execute("CN", [])
+        formal_parameter = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+        self.mvs.execute("CD", [new_frame, "caller", inst])
+        self.mvs.execute("CD", [new_frame, "prev", task_frame])
+        self.mvs.execute("CD", [new_frame, "symbols", symbols])
+        self.mvs.execute("CD", [signature, "body", body])
+        self.mvs.execute("CD", [signature, "params", params])
+        self.mvs.execute("CD", [new_frame, "IP", body])
+        self.mvs.execute("CD", [inst, "last_param", last_param])
+        self.mvs.execute("CD", [last_param, "name", name])
+
+        t1 = self.mvs.execute("CE", [params, formal_parameter])
+        self.mvs.execute("CE", [t1, name])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), new_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)
+        new_frame = self.mvs.execute("RD", [task_root, "frame"])
+        self.assertNotEquals(new_frame, None)
+        self.assertEquals(self.mvs.execute("RD", [new_frame, "IP"]), body)
+        self.assertEquals(self.mvs.execute("RD", [new_frame, "caller"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [new_frame, "prev"]), task_frame)
+
+    def test_call_param_first_multi(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        inst = self.mvs.execute("CNV", [{"value":"call"}])
+        returnvalue = self.mvs.execute("CN", [])
+        body = self.mvs.execute("CN", [])
+        new_frame = self.mvs.execute("CN", [])
+        symbols = self.mvs.execute("CN", [])
+        signature = self.mvs.execute("CN", [])
+        params = self.mvs.execute("CN", [])
+        param_value = self.mvs.execute("CN", [])
+        next_param = self.mvs.execute("CN", [])
+        evalstack = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", params])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+        self.mvs.execute("CD", [signature, "body", body])
+        self.mvs.execute("CD", [signature, "params", params])
+        self.mvs.execute("CD", [inst, "params", params])
+        self.mvs.execute("CD", [inst, "last_param", self.mvs.execute("CN", [])])
+        self.mvs.execute("CD", [params, "next_param", next_param])
+        self.mvs.execute("CD", [params, "value", param_value])
+        self.mvs.execute("CD", [returnvalue, "body", body])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        new_frame = self.mvs.execute("RRD", [task_frame, "prev"])
+        self.assertNotEquals(new_frame, None)
+        new_frame = new_frame[0]
+        new_evalstack = self.mvs.execute("RD", [new_frame, "evalstack"])
+        self.assertNotEquals(new_evalstack, None)
+        new_symbols = self.mvs.execute("RD", [new_frame, "symbols"])
+        self.assertNotEquals(new_symbols, None)
+        new_returnvalue = self.mvs.execute("RD", [new_frame, "returnvalue"])
+        self.assertNotEquals(new_returnvalue, None)
+        new_caller = self.mvs.execute("RD", [new_frame, "caller"])
+        self.assertNotEquals(new_caller, None)
+        new_phase = self.mvs.execute("RD", [new_frame, "phase"])
+        self.assertNotEquals(new_phase, None)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [new_frame, "phase"])]), "init")
+        new_IP = self.mvs.execute("RD", [new_frame, "IP"])
+        self.assertNotEquals(new_IP, None)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), param_value)
+        self.assertEquals(self.mvs.execute("RD", [new_frame, "caller"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [new_frame, "prev"]), task_frame)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "phase"]), next_param)
+
+    def test_call_param_first_single(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        inst = self.mvs.execute("CNV", [{"value":"call"}])
+        returnvalue = self.mvs.execute("CN", [])
+        body = self.mvs.execute("CN", [])
+        new_frame = self.mvs.execute("CN", [])
+        symbols = self.mvs.execute("CN", [])
+        signature = self.mvs.execute("CN", [])
+        params = self.mvs.execute("CN", [])
+        param_value = self.mvs.execute("CN", [])
+        evalstack = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", params])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+        self.mvs.execute("CD", [signature, "body", body])
+        self.mvs.execute("CD", [inst, "params", params])
+        self.mvs.execute("CD", [inst, "last_param", params])
+        self.mvs.execute("CD", [params, "value", param_value])
+        self.mvs.execute("CD", [returnvalue, "body", body])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        new_frame = self.mvs.execute("RRD", [task_frame, "prev"])
+        self.assertNotEquals(new_frame, None)
+        new_frame = new_frame[0]
+        new_evalstack = self.mvs.execute("RD", [new_frame, "evalstack"])
+        self.assertNotEquals(new_evalstack, None)
+        new_symbols = self.mvs.execute("RD", [new_frame, "symbols"])
+        self.assertNotEquals(new_symbols, None)
+        new_returnvalue = self.mvs.execute("RD", [new_frame, "returnvalue"])
+        self.assertNotEquals(new_returnvalue, None)
+        new_caller = self.mvs.execute("RD", [new_frame, "caller"])
+        self.assertNotEquals(new_caller, None)
+        new_phase = self.mvs.execute("RD", [new_frame, "phase"])
+        self.assertNotEquals(new_phase, None)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [new_frame, "phase"])]), "init")
+        new_IP = self.mvs.execute("RD", [new_frame, "IP"])
+        self.assertNotEquals(new_IP, None)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), param_value)
+        self.assertEquals(self.mvs.execute("RD", [new_frame, "caller"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [new_frame, "prev"]), task_frame)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [evalstack, "phase"])]), "call")
+
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+
+    def test_params_last(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        inst = self.mvs.execute("CNV", [{"value":"call"}])
+        returnvalue = self.mvs.execute("CN", [])
+        body = self.mvs.execute("CN", [])
+        new_frame = self.mvs.execute("CN", [])
+        symbols = self.mvs.execute("CN", [])
+        signature = self.mvs.execute("CN", [])
+        params = self.mvs.execute("CN", [])
+        param_value = self.mvs.execute("CN", [])
+        evalstack = self.mvs.execute("CN", [])
+        last_param = self.mvs.execute("CN", [])
+        prev_param = self.mvs.execute("CN", [])
+        formal_parameter = self.mvs.execute("CN", [])
+        formal_parameter_name = self.mvs.execute("CNV", ["param_a"])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", last_param])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+        self.mvs.execute("CD", [inst, "last_param", last_param])
+        self.mvs.execute("CD", [inst, "params", prev_param])
+        self.mvs.execute("CD", [params, "value", param_value])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+        self.mvs.execute("CD", [new_frame, "caller", inst])
+        self.mvs.execute("CD", [new_frame, "prev", task_frame])
+        self.mvs.execute("CD", [new_frame, "symbols", symbols])
+        self.mvs.execute("CD", [new_frame, "IP", body])
+        self.mvs.execute("CD", [signature, "body", body])
+        self.mvs.execute("CD", [signature, "params", params])
+        self.mvs.execute("CD", [prev_param, "next_param", last_param])
+        self.mvs.execute("CD", [prev_param, "name", formal_parameter_name])
+        self.mvs.execute("CD", [last_param, "value", param_value])
+        t1 = self.mvs.execute("CE", [params, formal_parameter])
+        self.mvs.execute("CE", [t1, formal_parameter_name])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), param_value)
+        var = self.mvs.execute("RDN", [symbols, formal_parameter])
+        self.assertNotEquals(var, None)
+        self.assertEquals(self.mvs.execute("RD", [var, "value"]), returnvalue)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [evalstack, "phase"])]), "call")
+
+    def test_params_next(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        inst = self.mvs.execute("CNV", [{"value":"call"}])
+        returnvalue = self.mvs.execute("CN", [])
+        body = self.mvs.execute("CN", [])
+        new_frame = self.mvs.execute("CN", [])
+        symbols = self.mvs.execute("CN", [])
+        signature = self.mvs.execute("CN", [])
+        params = self.mvs.execute("CN", [])
+        param_value = self.mvs.execute("CN", [])
+        evalstack = self.mvs.execute("CN", [])
+        formal_parameter = self.mvs.execute("CN", [])
+        formal_parameter_name = self.mvs.execute("CNV", ["param_a"])
+
+        param_a = self.mvs.execute("CN", [])
+        param_b = self.mvs.execute("CN", [])
+        param_c = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", param_b])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [inst, "params", self.mvs.execute("CN", [])])
+        self.mvs.execute("CD", [inst, "last_param", self.mvs.execute("CN", [])])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+        self.mvs.execute("CD", [params, "value", param_value])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+        self.mvs.execute("CD", [new_frame, "caller", inst])
+        self.mvs.execute("CD", [new_frame, "prev", task_frame])
+        self.mvs.execute("CD", [new_frame, "symbols", symbols])
+        self.mvs.execute("CD", [new_frame, "IP", body])
+        self.mvs.execute("CD", [signature, "body", body])
+        self.mvs.execute("CD", [signature, "params", params])
+        self.mvs.execute("CD", [param_a, "name", formal_parameter_name])
+        self.mvs.execute("CD", [param_b, "value", param_value])
+        self.mvs.execute("CD", [param_a, "next_param", param_b])
+        self.mvs.execute("CD", [param_b, "next_param", param_c])
+        t1 = self.mvs.execute("CE", [params, formal_parameter])
+        self.mvs.execute("CE", [t1, formal_parameter_name])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), param_value)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "phase"]), param_c)
+        var = self.mvs.execute("RDN", [symbols, formal_parameter])
+        self.assertNotEquals(var, None)
+        self.assertEquals(self.mvs.execute("RD", [var, "value"]), returnvalue)

+ 35 - 0
kernel/test_generated/rules/test_rules_constant.py

@@ -0,0 +1,35 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper
+
+class Testconstant(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+    def test_constant(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"constant"}])
+        node = self.mvs.execute("CN", [])
+        returnvalue = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+        self.mvs.execute("CD", [inst, "node", node])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [inst, "node"]), node)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "returnvalue"]), node)

+ 43 - 0
kernel/test_generated/rules/test_rules_continue.py

@@ -0,0 +1,43 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper
+
+class Testcontinue(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+    def test_basic(self):
+        # Create a continue construct
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"continue"}])
+        while_inst = self.mvs.execute("CNV", ["while"])
+        evalstack_top = self.mvs.execute("CN", [])
+        evalstack_bottom = self.mvs.execute("CN", [])
+        init_phase = self.mvs.execute("CNV", ["finish"])
+
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack_top])
+        self.mvs.execute("CD", [evalstack_top, "prev", evalstack_bottom])
+        self.mvs.execute("CD", [evalstack_bottom, "inst", while_inst])
+        self.mvs.execute("CD", [evalstack_bottom, "task_1", while_inst])
+        self.mvs.execute("CD", [evalstack_bottom, "phase", init_phase])
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [inst, "while", while_inst])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command inited, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [inst, "while"]), while_inst)
+        self.assertNotEquals(self.mvs.execute("RD", [task_frame, "evalstack"]), evalstack_top)

+ 63 - 0
kernel/test_generated/rules/test_rules_helper.py

@@ -0,0 +1,63 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper
+
+class TestHelper(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+    def test_next(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["finish"])
+        inst = self.mvs.execute("CN", [])
+        next_inst = self.mvs.execute("CNV", ["next"])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [inst, "next", next_inst])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [inst, "next"]), next_inst)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), next_inst)
+
+    def test_evalstack(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["finish"])
+        inst = self.mvs.execute("CN", [])
+        evalstack = self.mvs.execute("CN", [])
+        prev_evalstack = self.mvs.execute("CN", [])
+        evalstack_inst = self.mvs.execute("CN", [])
+        evalstack_phase = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+        self.mvs.execute("CD", [evalstack, "prev", prev_evalstack])
+        self.mvs.execute("CD", [prev_evalstack, "inst", evalstack_inst])
+        self.mvs.execute("CD", [prev_evalstack, "phase", evalstack_phase])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), evalstack_inst)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "phase"]), evalstack_phase)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "evalstack"]), prev_evalstack)

+ 128 - 0
kernel/test_generated/rules/test_rules_if.py

@@ -0,0 +1,128 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper
+
+class Testif(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+    def test_if_evaluate_condition(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"if"}])
+        evalstack = self.mvs.execute("CN", [])
+        cond = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [inst, "cond", cond])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), cond)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [evalstack, "phase"])]), "cond")
+
+    def test_if_true(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["cond"])
+        inst = self.mvs.execute("CNV", [{"value":"if"}])
+        evalstack = self.mvs.execute("CN", [])
+        returnvalue = self.mvs.execute("CNV", [True])
+        then = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+        self.mvs.execute("CD", [inst, "then", then])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), then)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [evalstack, "phase"])]), "finish")
+
+    def test_if_false_else(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["cond"])
+        inst = self.mvs.execute("CNV", [{"value":"if"}])
+        evalstack = self.mvs.execute("CN", [])
+        returnvalue = self.mvs.execute("CNV", [False])
+        else_inst = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+        self.mvs.execute("CD", [inst, "else", else_inst])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), else_inst)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [evalstack, "phase"])]), "finish")
+
+    def test_if_false_no_else(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["cond"])
+        inst = self.mvs.execute("CNV", [{"value":"if"}])
+        evalstack = self.mvs.execute("CN", [])
+        returnvalue = self.mvs.execute("CNV", [False])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)

+ 67 - 0
kernel/test_generated/rules/test_rules_input.py

@@ -0,0 +1,67 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper
+
+class TestInput(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+    def test_input(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"input"}])
+        old_retval = self.mvs.execute("CN", [])
+        input_queue_first = self.mvs.execute("CN", [])
+        input_queue_next = self.mvs.execute("CN", [])
+        value = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "returnvalue", old_retval])
+        self.mvs.execute("CD", [task_root, "input", input_queue_first])
+        self.mvs.execute("CD", [input_queue_first, "value", value])
+        self.mvs.execute("CD", [input_queue_first, "next", input_queue_next])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "returnvalue"]), value)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "input"]), input_queue_next)
+
+    def test_input_none(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"input"}])
+        old_retval = self.mvs.execute("CN", [])
+        input_queue_first = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "returnvalue", old_retval])
+        self.mvs.execute("CD", [task_root, "input", input_queue_first])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "returnvalue"]), old_retval)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "input"]), input_queue_first)

+ 70 - 0
kernel/test_generated/rules/test_rules_output.py

@@ -0,0 +1,70 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper
+
+class TestOutput(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+    def test_output_init(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"output"}])
+        value = self.mvs.execute("CN", [])
+        evalstack = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+        self.mvs.execute("CD", [inst, "value", value])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), value)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(new_evalstack, evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [evalstack, "phase"])]), "output")
+
+    def test_output_output(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["output"])
+        inst = self.mvs.execute("CNV", [{"value":"output"}])
+        retval = self.mvs.execute("CN", [])
+        output_queue = self.mvs.execute("CN", [])
+        value = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "returnvalue", retval])
+        self.mvs.execute("CD", [task_root, "last_output", output_queue])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "returnvalue"]), retval)
+        output_queue_next = self.mvs.execute("RD", [task_root, "last_output"])
+        self.assertNotEquals(output_queue_next, output_queue)
+        self.assertEquals(self.mvs.execute("RD", [output_queue, "next"]), output_queue_next)
+        self.assertEquals(self.mvs.execute("RD", [output_queue, "value"]), retval)

+ 115 - 0
kernel/test_generated/rules/test_rules_resolve.py

@@ -0,0 +1,115 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper
+
+class Testresolve(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+    def test_resolve_init_local(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"resolve"}])
+        var_inst = self.mvs.execute("CN", [])
+        symbols = self.mvs.execute("CN", [])
+        returnvalue = self.mvs.execute("CN", [])
+        entry = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [inst, "var", var_inst])
+        self.mvs.execute("CD", [task_frame, "symbols", symbols])
+        self.mvs.execute("CD", [task_frame, "returnvalue", self.mvs.execute("CN", [])])
+        self.mvs.execute("CD", [task_frame, "evalstack", self.mvs.execute("CN", [])])
+
+        t1 = self.mvs.execute("CE", [symbols, entry])
+        self.mvs.execute("CE", [t1, var_inst])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "returnvalue"]), entry)
+
+    def test_resolve_init_global(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        _globals = self.mvs.execute("CN", [])
+        self.mvs.execute("CD", [task_root, "globals", _globals])
+        global_task = self.mvs.execute("RD", [task_root, "globals"])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"resolve"}])
+        var_inst = self.mvs.execute("CNV", ["var"])
+        symbols = self.mvs.execute("CN", [])
+        returnvalue = self.mvs.execute("CN", [])
+        entry = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [inst, "var", var_inst])
+        self.mvs.execute("CD", [task_frame, "symbols", symbols])
+        self.mvs.execute("CD", [task_frame, "returnvalue", self.mvs.execute("CN", [])])
+        self.mvs.execute("CD", [task_frame, "evalstack", self.mvs.execute("CN", [])])
+
+        t1 = self.mvs.execute("CE", [global_task, entry])
+        self.mvs.execute("CE", [t1, var_inst])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "returnvalue"]), entry)
+
+    def test_resolve_init_local_over_global(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        global_task = self.mvs.execute("RD", [task_root, "globals"])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"resolve"}])
+        var_inst = self.mvs.execute("CNV", ["var"])
+        symbols = self.mvs.execute("CN", [])
+        returnvalue = self.mvs.execute("CN", [])
+        local_entry = self.mvs.execute("CN", [])
+        global_entry = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [inst, "var", var_inst])
+        self.mvs.execute("CD", [task_frame, "symbols", symbols])
+        self.mvs.execute("CD", [task_frame, "returnvalue", self.mvs.execute("CN", [])])
+        self.mvs.execute("CD", [task_frame, "evalstack", self.mvs.execute("CN", [])])
+
+        t1 = self.mvs.execute("CE", [global_task, global_entry])
+        self.mvs.execute("CE", [t1, var_inst])
+        t2 = self.mvs.execute("CE", [symbols, local_entry])
+        self.mvs.execute("CE", [t2, var_inst])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "returnvalue"]), local_entry)

+ 86 - 0
kernel/test_generated/rules/test_rules_return.py

@@ -0,0 +1,86 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper
+
+class Testreturn(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+    def test_return_init(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"return"}])
+        prev_stackframe = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "prev", prev_stackframe])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), prev_stackframe)
+
+    def test_return_init_value(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"return"}])
+        evalstack = self.mvs.execute("CN", [])
+        value = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [inst, "value", value])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), value)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [evalstack, "phase"])]), "eval")
+
+    def test_return_eval(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["eval"])
+        inst = self.mvs.execute("CNV", [{"value":"return"}])
+        prev_stackframe = self.mvs.execute("CN", [])
+        returnvalue_top = self.mvs.execute("CN", [])
+        returnvalue_bottom = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "prev", prev_stackframe])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue_top])
+        self.mvs.execute("CD", [prev_stackframe, "returnvalue", returnvalue_bottom])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), prev_stackframe)
+        self.assertEquals(self.mvs.execute("RD", [prev_stackframe, "returnvalue"]), returnvalue_top)

+ 28 - 0
kernel/test_generated/rules/test_rules_utility.py

@@ -0,0 +1,28 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+
+class TestUtility(unittest.TestCase):
+    def test_overlap_normal(self):
+        c = ModelverseKernel(0).find_overlapping([1, 2, 3], [2, 4])
+        self.assertEquals(c, 2)
+
+    def test_overlap_none_empty(self):
+        try:
+            ModelverseKernel(0).find_overlapping([], [2, 4])
+            self.fail() # pragma: no cover
+        except:
+            pass
+
+    def test_overlap_none(self):
+        try:
+            ModelverseKernel(0).find_overlapping([1, 3], [2, 4, 5])
+            self.fail() # pragma: no cover
+        except:
+            pass
+
+    def test_overlap_multi(self):
+        try:
+            ModelverseKernel(0).find_overlapping([1, 2, 3], [2, 4, 1])
+            self.fail() # pragma: no cover
+        except:
+            pass

+ 94 - 0
kernel/test_generated/rules/test_rules_while.py

@@ -0,0 +1,94 @@
+import unittest
+from modelverse_kernel.generated import ModelverseKernel
+from utils import execute_until_finished, MvSWrapper
+
+class Testwhile(unittest.TestCase):
+    def setUp(self):
+        self.mvs = MvSWrapper()
+        self.root = self.mvs.execute("RR", [])
+        self.mvk = ModelverseKernel(self.root)
+
+    def test_while_evaluate_condition(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["init"])
+        inst = self.mvs.execute("CNV", [{"value":"while"}])
+        evalstack = self.mvs.execute("CN", [])
+        cond = self.mvs.execute("CN", [])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [inst, "cond", cond])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), cond)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [evalstack, "phase"])]), "cond")
+
+    def test_while_true(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["cond"])
+        inst = self.mvs.execute("CNV", [{"value":"while"}])
+        evalstack = self.mvs.execute("CN", [])
+        body = self.mvs.execute("CN", [])
+        returnvalue = self.mvs.execute("CNV", [True])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [inst, "body", body])
+        self.mvs.execute("CD", [task_frame, "evalstack", evalstack])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "init")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), body)
+        new_evalstack = self.mvs.execute("RD", [task_frame, "evalstack"])
+        self.assertNotEquals(evalstack, new_evalstack)
+        self.assertEquals(self.mvs.execute("RD", [new_evalstack, "prev"]), evalstack)
+        self.assertEquals(self.mvs.execute("RD", [evalstack, "inst"]), inst)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [evalstack, "phase"])]), "init")
+
+    def test_while_false(self):
+        root = self.root
+        task_root = self.mvs.execute("CN", [])
+        task_frame = self.mvs.execute("CN", [])
+        phase = self.mvs.execute("CNV", ["cond"])
+        inst = self.mvs.execute("CNV", [{"value":"while"}])
+        returnvalue = self.mvs.execute("CNV", [False])
+
+        self.mvs.execute("CD", [root, "task_1", task_root])
+        self.mvs.execute("CD", [task_root, "frame", task_frame])
+        self.mvs.execute("CD", [task_frame, "phase", phase])
+        self.mvs.execute("CD", [task_frame, "IP", inst])
+        self.mvs.execute("CD", [task_frame, "returnvalue", returnvalue])
+
+        # Do the invocation until it returns None
+        execute_until_finished(self.mvk, self.mvs)
+
+        # Execution of the command finished, so the MvS should be in the correct new state right now
+        self.assertEquals(self.mvs.execute("RD", [root, "task_1"]), task_root)
+        self.assertEquals(self.mvs.execute("RD", [task_root, "frame"]), task_frame)
+        self.assertEquals(self.mvs.execute("RV", [self.mvs.execute("RD", [task_frame, "phase"])]), "finish")
+        self.assertEquals(self.mvs.execute("RD", [task_frame, "IP"]), inst)

+ 120 - 0
kernel/test_generated/rules/utils.py

@@ -0,0 +1,120 @@
+import sys
+sys.path.append("../state")
+from modelverse_state.main import ModelverseState
+import json
+
+class MvSWrapper(object):
+    def __init__(self):
+        self.mvs = ModelverseState("../bootstrap/minimal.m.gz")
+
+        self.mapping = {
+                   "RD": self.mvs.read_dict,
+                   "RR": self.mvs.read_root,
+                   "RO": self.mvs.read_outgoing,
+                   "RI": self.mvs.read_incoming,
+                   "RE": self.mvs.read_edge,
+                   "RDE": self.mvs.read_dict_edge,
+                   "RDK": self.mvs.read_dict_keys,
+                   "RDN": self.mvs.read_dict_node,
+                   "RDNE": self.mvs.read_dict_node_edge,
+                   "RRD": self.mvs.read_reverse_dict,
+                   "RV": self.mvs.read_value,
+                   "CN": self.mvs.create_node,
+                   "CNV": self.mvs.create_nodevalue,
+                   "CE": self.mvs.create_edge,
+                   "DE": self.mvs.delete_edge,
+                   "DN": self.mvs.delete_node,
+                   "CD": self.mvs.create_dict,
+                  }
+
+    def execute(self, command, params):
+        params = json.loads(json.dumps(params))
+        retval = self.mapping[command](*params)
+        retval = json.loads(json.dumps(retval))
+
+        return retval
+
+def add_new_task(root, mvs, taskname):
+    hierarchy = mvs.execute("RD", [root, "__hierarchy"])
+    initial = mvs.execute("RD", [hierarchy, "__IP"])
+
+    task_root = mvs.execute("CN", [])
+    _globals = mvs.execute("CN", [])
+    frame = mvs.execute("CN", [])
+    evalstack = mvs.execute("CN", [])
+    symbols = mvs.execute("CN", [])
+    _input = mvs.execute("CN", [])
+    _output = mvs.execute("CN", [])
+    returnvalue = mvs.execute("CN", [])
+    phase = mvs.execute("CNV", ["init"])
+
+    mvs.execute("CD", [root, taskname, task_root])
+    mvs.execute("CD", [task_root, "frame", frame])
+    mvs.execute("CD", [task_root, "globals", _globals])
+    mvs.execute("CD", [task_root, "input", _input])
+    mvs.execute("CD", [task_root, "last_input", _input])
+    mvs.execute("CD", [task_root, "output", _output])
+    mvs.execute("CD", [task_root, "last_output", _output])
+    mvs.execute("CD", [frame, "evalstack", evalstack])
+    mvs.execute("CD", [frame, "returnvalue", returnvalue])
+    mvs.execute("CD", [frame, "phase", phase])
+    mvs.execute("CD", [frame, "IP", initial])
+    mvs.execute("CD", [frame, "symbols", symbols])
+
+def execute_until_finished(mvk, mvs, operation="execute_rule", params=[]):
+    taskname = "task_1"
+    if operation == "initialize_new_task":
+        return add_new_task(mvk.root, mvs, taskname)
+    response = None
+    while 1:
+        mvs_commands = mvk.execute_yields(taskname, operation, params, response)
+        if mvs_commands is None:
+            break
+        response = []
+        for command, param in mvs_commands:
+            response.append(mvs.execute(command, param))
+
+def get_inst(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    inst = mvs.execute("RD", [task_frame, "IP"])
+    return mvs.execute("RV", [inst])["value"]
+
+def get_phase(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    phase = mvs.execute("RD", [task_frame, "phase"])
+    return mvs.execute("RV", [phase])
+
+def get_returnvalue(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    returnvalue = mvs.execute("RD", [task_frame, "returnvalue"])
+    return mvs.execute("RV", [returnvalue])
+
+def get_inst_ref(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    return mvs.execute("RD", [task_frame, "IP"])
+
+def get_returnvalue_ref(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    return mvs.execute("RD", [task_frame, "returnvalue"])
+
+def get_phase_ref(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    phase = mvs.execute("RD", [task_frame, "phase"])
+    return phase
+
+def read_primitive_interfaces(root, mvs):
+    hierarchy = mvs.execute("RD", [root, "__hierarchy"])
+    primitives = mvs.execute("RD", [hierarchy, "primitives"])
+    keys = mvs.execute("RDK", [primitives])
+    d = {}
+    for k in keys:
+        value = mvs.execute("RDN", [primitives, k])
+        name = mvs.execute("RV", [k])
+        d[name] = value
+    return d

+ 120 - 0
kernel/test_generated/utils.py

@@ -0,0 +1,120 @@
+import sys
+sys.path.append("../state")
+from modelverse_state.main import ModelverseState
+import json
+
+class MvSWrapper(object):
+    def __init__(self):
+        self.mvs = ModelverseState("../bootstrap/minimal.m.gz")
+
+        self.mapping = {
+                   "RD": self.mvs.read_dict,
+                   "RR": self.mvs.read_root,
+                   "RO": self.mvs.read_outgoing,
+                   "RI": self.mvs.read_incoming,
+                   "RE": self.mvs.read_edge,
+                   "RDE": self.mvs.read_dict_edge,
+                   "RDK": self.mvs.read_dict_keys,
+                   "RDN": self.mvs.read_dict_node,
+                   "RDNE": self.mvs.read_dict_node_edge,
+                   "RRD": self.mvs.read_reverse_dict,
+                   "RV": self.mvs.read_value,
+                   "CN": self.mvs.create_node,
+                   "CNV": self.mvs.create_nodevalue,
+                   "CE": self.mvs.create_edge,
+                   "DE": self.mvs.delete_edge,
+                   "DN": self.mvs.delete_node,
+                   "CD": self.mvs.create_dict,
+                  }
+
+    def execute(self, command, params):
+        params = json.loads(json.dumps(params))
+        retval = self.mapping[command](*params)
+        retval = json.loads(json.dumps(retval))
+
+        return retval
+
+def add_new_task(root, mvs, taskname):
+    hierarchy = mvs.execute("RD", [root, "__hierarchy"])
+    initial = mvs.execute("RD", [hierarchy, "__IP"])
+
+    task_root = mvs.execute("CN", [])
+    _globals = mvs.execute("CN", [])
+    frame = mvs.execute("CN", [])
+    evalstack = mvs.execute("CN", [])
+    symbols = mvs.execute("CN", [])
+    _input = mvs.execute("CN", [])
+    _output = mvs.execute("CN", [])
+    returnvalue = mvs.execute("CN", [])
+    phase = mvs.execute("CNV", ["init"])
+
+    mvs.execute("CD", [root, taskname, task_root])
+    mvs.execute("CD", [task_root, "frame", frame])
+    mvs.execute("CD", [task_root, "globals", _globals])
+    mvs.execute("CD", [task_root, "input", _input])
+    mvs.execute("CD", [task_root, "last_input", _input])
+    mvs.execute("CD", [task_root, "output", _output])
+    mvs.execute("CD", [task_root, "last_output", _output])
+    mvs.execute("CD", [frame, "evalstack", evalstack])
+    mvs.execute("CD", [frame, "returnvalue", returnvalue])
+    mvs.execute("CD", [frame, "phase", phase])
+    mvs.execute("CD", [frame, "IP", initial])
+    mvs.execute("CD", [frame, "symbols", symbols])
+
+def execute_until_finished(mvk, mvs, operation="execute_rule", params=[]):
+    taskname = "task_1"
+    if operation == "initialize_new_task":
+        return add_new_task(mvk.root, mvs, taskname)
+    response = None
+    while 1:
+        mvs_commands = mvk.execute_yields(taskname, operation, params, response)
+        if mvs_commands is None:
+            break
+        response = []
+        for command, param in mvs_commands:
+            response.append(mvs.execute(command, param))
+
+def get_inst(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    inst = mvs.execute("RD", [task_frame, "IP"])
+    return mvs.execute("RV", [inst])["value"]
+
+def get_phase(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    phase = mvs.execute("RD", [task_frame, "phase"])
+    return mvs.execute("RV", [phase])
+
+def get_returnvalue(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    returnvalue = mvs.execute("RD", [task_frame, "returnvalue"])
+    return mvs.execute("RV", [returnvalue])
+
+def get_inst_ref(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    return mvs.execute("RD", [task_frame, "IP"])
+
+def get_returnvalue_ref(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    return mvs.execute("RD", [task_frame, "returnvalue"])
+
+def get_phase_ref(root, mvs):
+    task_root = mvs.execute("RD", [root, "task_1"])
+    task_frame = mvs.execute("RD", [task_root, "frame"])
+    phase = mvs.execute("RD", [task_frame, "phase"])
+    return phase
+
+def read_primitive_interfaces(root, mvs):
+    hierarchy = mvs.execute("RD", [root, "__hierarchy"])
+    primitives = mvs.execute("RD", [hierarchy, "primitives"])
+    keys = mvs.execute("RDK", [primitives])
+    d = {}
+    for k in keys:
+        value = mvs.execute("RDN", [primitives, k])
+        name = mvs.execute("RV", [k])
+        d[name] = value
+    return d