turing.ncd 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. process main {
  2. # Turing machine specification.
  3. var("B") blank;
  4. var([
  5. {"0", "0"}:{"0", "0", "right"},
  6. {"0", "1"}:{"1", "x", "right"},
  7. {"1", "1"}:{"1", "1", "right"},
  8. {"1", "0"}:{"2", "0", "right"},
  9. {"2", "0"}:{"2", "0", "right"},
  10. {"2", "1"}:{"3", "1", "right"},
  11. {"3", "1"}:{"3", "1", "right"},
  12. {"3", "0"}:{"4", "1", "left"},
  13. {"3", "B"}:{"4", "1", "left"},
  14. {"4", "1"}:{"4", "1", "left"},
  15. {"4", "0"}:{"5", "0", "left"},
  16. {"5", "0"}:{"5", "0", "left"},
  17. {"5", "1"}:{"6", "1", "left"},
  18. {"5", "x"}:{"h", "x", "stay"},
  19. {"6", "1"}:{"6", "1", "left"},
  20. {"6", "x"}:{"0", "x", "right"},
  21. {"6", "0"}:{"0", "0", "right"}
  22. ]) rules;
  23. var("0") initial_state;
  24. var({}) initial_tape_left;
  25. var({
  26. "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1",
  27. "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1",
  28. "0", "0",
  29. "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1",
  30. "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"
  31. }) initial_tape_right;
  32. # Perform the computation, stopping when no rule matches.
  33. call("turing", {blank, rules, initial_state, initial_tape_left, initial_tape_right}) results;
  34. # Check results.
  35. val_equal(results.tape_left, {"B"}) a;
  36. assert(a);
  37. val_equal(results.tape_right,
  38. {"x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x",
  39. "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x", "x",
  40. "0", "0", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1",
  41. "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1",
  42. "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1",
  43. "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1",
  44. "1", "1"}
  45. ) a;
  46. assert(a);
  47. val_equal({results.side, results.pos}, {"right", "55"}) a;
  48. assert(a);
  49. val_equal(results.state, "h") a;
  50. assert(a);
  51. exit("0");
  52. }
  53. template turing {
  54. alias("_arg0") blank;
  55. value(_arg1) rules;
  56. alias("_arg2") initial_state;
  57. alias("_arg3") initial_tape_left;
  58. alias("_arg4") initial_tape_right;
  59. # Head state.
  60. var(initial_state) state;
  61. # Tape. Positions go like this: ... L2 L1 L0 R0 R1 R2 ...
  62. value(initial_tape_left) tape_left;
  63. value(initial_tape_right) tape_right;
  64. # Make sure each side of the tape has at least one symbol so we can flip easily.
  65. tape_left->insert(tape_left.length, blank);
  66. tape_right->insert(tape_right.length, blank);
  67. # Head position.
  68. var("right") side;
  69. var("0") pos;
  70. # Enter loop.
  71. blocker() loop_blk;
  72. loop_blk->up();
  73. loop_blk->use();
  74. # Get symbol under head.
  75. concat("tape_", side) tape_name;
  76. alias(tape_name) cur_tape;
  77. cur_tape->get(pos) symbol;
  78. # Look for a matching rule.
  79. rules->try_get({state, symbol}) rule;
  80. If (rule.exists) {
  81. # Extract directions from rule.
  82. rule->get("0") new_state;
  83. rule->get("1") new_symbol;
  84. rule->get("2") move;
  85. # Change head state.
  86. state->set(new_state);
  87. # Replace symbol under head.
  88. cur_tape->remove(pos);
  89. cur_tape->insert(pos, new_symbol);
  90. # Branch based on how we move.
  91. strcmp(move, side) is_outside;
  92. strcmp(move, "stay") is_stay;
  93. strcmp(pos, "0") is_zero;
  94. If (is_outside) {
  95. # Increment position.
  96. num_add(pos, "1") new_pos;
  97. pos->set(new_pos);
  98. # If the new position is out of range, extend tape.
  99. strcmp(pos, cur_tape.length) need_extend;
  100. If (need_extend) {
  101. cur_tape->insert(pos, blank);
  102. };
  103. } elif (is_stay) {
  104. # Nop.
  105. getargs();
  106. } elif (is_zero) {
  107. # Flip side, leave pos at zero.
  108. side->set(move);
  109. } else {
  110. # Decrement position.
  111. num_subtract(pos, "1") new_pos;
  112. pos->set(new_pos);
  113. };
  114. # Continue loop.
  115. loop_blk->downup();
  116. };
  117. }