nudge 0.2.6 → 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (156) hide show
  1. data/VERSION +1 -1
  2. data/lib/instructions/bool/bool_and.rb +8 -0
  3. data/lib/instructions/bool/bool_define.rb +9 -0
  4. data/lib/instructions/bool/bool_depth.rb +5 -0
  5. data/lib/instructions/bool/bool_duplicate.rb +7 -0
  6. data/lib/instructions/bool/bool_equal_q.rb +8 -0
  7. data/lib/instructions/bool/bool_flush.rb +3 -0
  8. data/lib/instructions/bool/bool_not.rb +8 -0
  9. data/lib/instructions/bool/bool_or.rb +8 -0
  10. data/lib/instructions/bool/bool_pop.rb +3 -0
  11. data/lib/instructions/bool/bool_random.rb +3 -0
  12. data/lib/instructions/bool/bool_rotate.rb +11 -0
  13. data/lib/instructions/bool/bool_shove.rb +14 -0
  14. data/lib/instructions/bool/bool_swap.rb +3 -0
  15. data/lib/instructions/bool/bool_xor.rb +8 -0
  16. data/lib/instructions/bool/bool_yank.rb +12 -0
  17. data/lib/instructions/bool/bool_yankdup.rb +12 -0
  18. data/lib/instructions/code/code_atom_q.rb +9 -0
  19. data/lib/instructions/code/code_backbone_points.rb +17 -0
  20. data/lib/instructions/code/code_car.rb +15 -0
  21. data/lib/instructions/code/code_cdr.rb +13 -1
  22. data/lib/instructions/code/code_concatenate.rb +20 -0
  23. data/lib/instructions/code/code_cons.rb +22 -1
  24. data/lib/instructions/code/code_container.rb +21 -2
  25. data/lib/instructions/code/code_contains_q.rb +11 -0
  26. data/lib/instructions/code/code_define.rb +9 -0
  27. data/lib/instructions/code/code_depth.rb +5 -0
  28. data/lib/instructions/code/code_discrepancy.rb +13 -7
  29. data/lib/instructions/code/code_do_count.rb +21 -1
  30. data/lib/instructions/code/code_do_range.rb +44 -3
  31. data/lib/instructions/code/code_do_times.rb +39 -1
  32. data/lib/instructions/code/code_duplicate.rb +7 -0
  33. data/lib/instructions/code/code_equal_q.rb +9 -0
  34. data/lib/instructions/code/code_execute.rb +7 -0
  35. data/lib/instructions/code/code_execute_then_pop.rb +9 -0
  36. data/lib/instructions/code/code_flush.rb +3 -0
  37. data/lib/instructions/code/code_gsub.rb +11 -3
  38. data/lib/instructions/code/code_if.rb +8 -0
  39. data/lib/instructions/code/code_instructions.rb +12 -0
  40. data/lib/instructions/code/code_list.rb +10 -0
  41. data/lib/instructions/code/code_member_q.rb +14 -0
  42. data/lib/instructions/code/code_name_lookup.rb +10 -0
  43. data/lib/instructions/code/code_noop.rb +3 -0
  44. data/lib/instructions/code/code_nth.rb +12 -0
  45. data/lib/instructions/code/code_nth_cdr.rb +14 -2
  46. data/lib/instructions/code/code_nth_point.rb +15 -0
  47. data/lib/instructions/code/code_null_q.rb +11 -0
  48. data/lib/instructions/code/code_parses_q.rb +8 -0
  49. data/lib/instructions/code/code_points.rb +8 -0
  50. data/lib/instructions/code/code_pop.rb +3 -0
  51. data/lib/instructions/code/code_position.rb +11 -0
  52. data/lib/instructions/code/code_quote.rb +11 -0
  53. data/lib/instructions/code/code_replace_nth_point.rb +11 -0
  54. data/lib/instructions/code/code_rotate.rb +11 -0
  55. data/lib/instructions/code/code_shove.rb +14 -0
  56. data/lib/instructions/code/code_swap.rb +3 -0
  57. data/lib/instructions/code/code_yank.rb +12 -0
  58. data/lib/instructions/code/code_yankdup.rb +12 -0
  59. data/lib/instructions/conversion/bool_from_float.rb +9 -0
  60. data/lib/instructions/conversion/bool_from_int.rb +9 -0
  61. data/lib/instructions/conversion/code_from_bool.rb +9 -1
  62. data/lib/instructions/conversion/code_from_float.rb +10 -1
  63. data/lib/instructions/conversion/code_from_int.rb +10 -1
  64. data/lib/instructions/conversion/code_from_name.rb +10 -1
  65. data/lib/instructions/conversion/float_from_bool.rb +9 -0
  66. data/lib/instructions/conversion/float_from_int.rb +9 -0
  67. data/lib/instructions/conversion/int_from_bool.rb +9 -0
  68. data/lib/instructions/conversion/int_from_float.rb +9 -0
  69. data/lib/instructions/exec/exec_define.rb +9 -0
  70. data/lib/instructions/exec/exec_depth.rb +5 -0
  71. data/lib/instructions/exec/exec_do_count.rb +22 -0
  72. data/lib/instructions/exec/exec_do_range.rb +43 -0
  73. data/lib/instructions/exec/exec_do_times.rb +40 -0
  74. data/lib/instructions/exec/exec_duplicate.rb +7 -0
  75. data/lib/instructions/exec/exec_equal_q.rb +9 -0
  76. data/lib/instructions/exec/exec_flush.rb +5 -0
  77. data/lib/instructions/exec/exec_if.rb +8 -0
  78. data/lib/instructions/exec/exec_k.rb +4 -0
  79. data/lib/instructions/exec/exec_pop.rb +3 -0
  80. data/lib/instructions/exec/exec_rotate.rb +11 -0
  81. data/lib/instructions/exec/exec_s.rb +11 -0
  82. data/lib/instructions/exec/exec_shove.rb +14 -0
  83. data/lib/instructions/exec/exec_swap.rb +3 -0
  84. data/lib/instructions/exec/exec_y.rb +18 -0
  85. data/lib/instructions/exec/exec_yank.rb +12 -0
  86. data/lib/instructions/exec/exec_yankdup.rb +12 -0
  87. data/lib/instructions/float/float_abs.rb +8 -0
  88. data/lib/instructions/float/float_add.rb +8 -0
  89. data/lib/instructions/float/float_cosine.rb +8 -0
  90. data/lib/instructions/float/float_define.rb +9 -0
  91. data/lib/instructions/float/float_depth.rb +5 -0
  92. data/lib/instructions/float/float_divide.rb +12 -0
  93. data/lib/instructions/float/float_duplicate.rb +7 -0
  94. data/lib/instructions/float/float_equal_q.rb +8 -0
  95. data/lib/instructions/float/float_flush.rb +3 -0
  96. data/lib/instructions/float/float_greater_than_q.rb +9 -0
  97. data/lib/instructions/float/float_if.rb +8 -0
  98. data/lib/instructions/float/float_less_than_q.rb +9 -0
  99. data/lib/instructions/float/float_max.rb +8 -0
  100. data/lib/instructions/float/float_min.rb +8 -0
  101. data/lib/instructions/float/float_modulo.rb +12 -0
  102. data/lib/instructions/float/float_multiply.rb +8 -0
  103. data/lib/instructions/float/float_negative.rb +8 -0
  104. data/lib/instructions/float/float_pop.rb +3 -0
  105. data/lib/instructions/float/float_power.rb +12 -0
  106. data/lib/instructions/float/float_random.rb +3 -0
  107. data/lib/instructions/float/float_rotate.rb +11 -0
  108. data/lib/instructions/float/float_shove.rb +14 -0
  109. data/lib/instructions/float/float_sine.rb +8 -0
  110. data/lib/instructions/float/float_sqrt.rb +10 -0
  111. data/lib/instructions/float/float_subtract.rb +10 -0
  112. data/lib/instructions/float/float_swap.rb +3 -0
  113. data/lib/instructions/float/float_tangent.rb +8 -0
  114. data/lib/instructions/float/float_yank.rb +12 -0
  115. data/lib/instructions/float/float_yankdup.rb +12 -0
  116. data/lib/instructions/int/int_abs.rb +9 -1
  117. data/lib/instructions/int/int_add.rb +8 -0
  118. data/lib/instructions/int/int_define.rb +10 -1
  119. data/lib/instructions/int/int_depth.rb +5 -0
  120. data/lib/instructions/int/int_divide.rb +12 -0
  121. data/lib/instructions/int/int_duplicate.rb +7 -0
  122. data/lib/instructions/int/int_equal_q.rb +8 -0
  123. data/lib/instructions/int/int_flush.rb +3 -0
  124. data/lib/instructions/int/int_greater_than_q.rb +9 -0
  125. data/lib/instructions/int/int_if.rb +8 -0
  126. data/lib/instructions/int/int_less_than_q.rb +9 -0
  127. data/lib/instructions/int/int_max.rb +8 -0
  128. data/lib/instructions/int/int_min.rb +8 -0
  129. data/lib/instructions/int/int_modulo.rb +12 -0
  130. data/lib/instructions/int/int_multiply.rb +8 -0
  131. data/lib/instructions/int/int_negative.rb +8 -0
  132. data/lib/instructions/int/int_pop.rb +3 -0
  133. data/lib/instructions/int/int_power.rb +12 -0
  134. data/lib/instructions/int/int_random.rb +3 -0
  135. data/lib/instructions/int/int_rotate.rb +11 -0
  136. data/lib/instructions/int/int_shove.rb +14 -0
  137. data/lib/instructions/int/int_subtract.rb +10 -0
  138. data/lib/instructions/int/int_swap.rb +3 -0
  139. data/lib/instructions/int/int_yank.rb +14 -0
  140. data/lib/instructions/int/int_yankdup.rb +14 -0
  141. data/lib/instructions/name/name_depth.rb +5 -0
  142. data/lib/instructions/name/name_disable_lookup.rb +11 -0
  143. data/lib/instructions/name/name_duplicate.rb +7 -0
  144. data/lib/instructions/name/name_equal_q.rb +8 -0
  145. data/lib/instructions/name/name_flush.rb +3 -0
  146. data/lib/instructions/name/name_next.rb +7 -0
  147. data/lib/instructions/name/name_pop.rb +3 -0
  148. data/lib/instructions/name/name_random_bound.rb +9 -0
  149. data/lib/instructions/name/name_rotate.rb +11 -0
  150. data/lib/instructions/name/name_shove.rb +14 -0
  151. data/lib/instructions/name/name_swap.rb +3 -0
  152. data/lib/instructions/name/name_unbind.rb +7 -0
  153. data/lib/instructions/name/name_yank.rb +12 -0
  154. data/lib/instructions/name/name_yankdup.rb +12 -0
  155. data/spec/instructions/code/code_nth_cdr_spec.rb +10 -2
  156. metadata +3 -3
@@ -1,4 +1,24 @@
1
- # Again, the original description of this instruction appears to be confusing "CODE.DO*RANGE" with "EXEC.DO*RANGE"; I've made the adjustment to the code so that the behavior is as described, not the implementation.
1
+ # Pops one "count" item from the +:int+ stack, and one item from the +:code+ stack.
2
+ # The net effect of the instruction (unless interfered with by another operation)
3
+ # is to evaluate the +:code+ item "count" times.
4
+ #
5
+ # If the count is negative, an +:error+ item will be pushed to the +:error+ stack. Otherwise,
6
+ # a ValuePoint containing the following "macro" is created and pushed onto the +:exec+ stack:
7
+ # block {
8
+ # value «int»
9
+ # value «int»
10
+ # do exec_do_range
11
+ # popped item
12
+ # }
13
+ # «int» 0
14
+ # «int» count - 1
15
+ # where +popped_item+ is the code from the +:code+ stack, and +count - 1+ is a decrement of
16
+ # the "count" value.
17
+ #
18
+ # *needs:* ExecDoRangeInstruction must be active in the context for this to work; needs 1 +:int+ and 1 +:code+ item
19
+ #
20
+ # *pushes:* it's complicated...
21
+ #
2
22
 
3
23
  class CodeDoCountInstruction < Instruction
4
24
  def preconditions?
@@ -1,6 +1,47 @@
1
- # ORIGINAL DESCRIPTION: An iteration instruction that executes the top item on the CODE stack a number of times that depends on the top two integers, while also pushing the loop counter onto the INTEGER stack for possible access during the execution of the body of the loop. The top integer is the "destination index" and the second integer is the "current index." First the code and the integer arguments are saved locally and popped. Then the integers are compared. If the integers are equal then the current index is pushed onto the INTEGER stack and the code (which is the "body" of the loop) is pushed onto the EXEC stack for subsequent execution. If the integers are not equal then the current index will still be pushed onto the INTEGER stack but two items will be pushed onto the EXEC stack -- first a recursive call to CODE.DO*RANGE (with the same code and destination index, but with a current index that has been either incremented or decremented by 1 to be closer to the destination index) and then the body code. Note that the range is inclusive of both endpoints; a call with integer arguments 3 and 5 will cause its body to be executed 3 times, with the loop counter having the values 3, 4, and 5. Note also that one can specify a loop that "counts down" by providing a destination index that is less than the specified current index.
2
-
3
- # That description must be flawed; "a recursive call to CODE.DO*RANGE" would not run the same code, but rather run the next piece of code from the :code stack. I'm interpreting it as a typo, and using exec_do_range instead, since that will have the desired outcome without running through all kinds of weird :code items.
1
+ # Pops two values from the +:int+ stack ("destination" and "counter"), and one item from the +:code+ stack.
2
+ # The net effect of the instruction (unless interfered with by another operation)
3
+ # is to evaluate the +:code+ item once for every integer in the range (inclusive), and
4
+ # at the same time push the counter integer onto the +:int+ stack.
5
+ #
6
+ # note: rather than duplicating the functionality of the ExecDoRangeInstruction, that is used as a macro here
7
+ #
8
+ # note: the first integer popped is the "destination", the second one the "counter"
9
+ # (regardless of their values or signs)
10
+ #
11
+ # note: unlike the CodeDoTimes instruction, the counter is pushed
12
+ #
13
+ # <b>If the counter and destination have the same value</b>, then a new +:int+ is pushed with that value,
14
+ # and the +:code+ item is pushed onto the +:exec+ stack.
15
+ #
16
+ # <b>If the counter and destination have different values</b>, then a "new_counter" value
17
+ # is calculated that is *one step closer to the destination*.
18
+ #
19
+ # A ValuePoint containing the following "macro" is created:
20
+ # block {
21
+ # value «int»
22
+ # value «int»
23
+ # do exec_do_range
24
+ # popped item
25
+ # }
26
+ # «int» new_counter
27
+ # «int» destination
28
+ # where +popped_item+ is the code from the +:code+ stack, and +new_counter+ and +destination+ are the numeric values that were derived above.
29
+ #
30
+ # Finally,
31
+ # 1. a new ValuePoint whose value is +new_counter+ is pushed to the +:int+ stack;
32
+ # 2. the macro is pushed onto the +:exec+ stack
33
+ # 3. another copy of the +popped_item+ is pushed onto the +:exec+ stack (on top of the macro)
34
+ #
35
+ # The consequence is that the original +:code+ item will be executed (at least once),
36
+ # the counter will be pushed onto the +:int+ stack,
37
+ # the macro will be encountered, and this cycle will repeat via the ExecDoRangeInstruction.
38
+ #
39
+ # note: if the +popped_item+ itself manipulates the +:exec+ stack, "complicated behavior" may arise
40
+ #
41
+ # *needs:* 2 +:int+ items, 1 +:code+ item
42
+ #
43
+ # *pushes:* well, it's complicated...
44
+ #
4
45
 
5
46
  class CodeDoRangeInstruction < Instruction
6
47
  def preconditions?
@@ -1,4 +1,42 @@
1
- # Again, the original description of this instruction appears to be confusing "CODE.DO*RANGE" with "EXEC.DO*RANGE"; I've made the adjustment to the code so that the behavior is as described, not the implementation.
1
+ # Pops two values from the +:int+ stack ("destination" and "counter"), and one item from the +:code+ stack.
2
+ # The net effect of the instruction (unless interfered with by another operation)
3
+ # is to evaluate the +:exec+ item once for every integer in the range (inclusive).
4
+ #
5
+ # note: the top integer is the "destination", the second one the "counter"
6
+ # (regardless of their values or signs)
7
+ #
8
+ # note: unlike the CodeDoRange instruction, the counter is not pushed
9
+ #
10
+ # <b>If the counter and destination have the same value</b>, then a copy of the +:code+ item is
11
+ # pushed onto the +:exec+ stack.
12
+ #
13
+ # <b>If the counter and destination have different values</b>, then a "new_counter" value
14
+ # is calculated that is *one step closer to the destination*.
15
+ #
16
+ # A ValuePoint containing the following "macro" is created:
17
+ # block {
18
+ # value «int»
19
+ # value «int»
20
+ # do exec_do_times
21
+ # popped item
22
+ # }
23
+ # «int» new_counter
24
+ # «int» destination
25
+ # where +popped_item+ is the code from the +:code+ stack, and +new_counter+ and +destination+ are the numeric values that were derived above.
26
+ #
27
+ # Finally,
28
+ # 1. the macro is pushed onto the +:exec+ stack
29
+ # 2. another copy of the +popped_item+ is pushed onto the +:exec+ stack (on top of the macro)
30
+ #
31
+ # The consequence is that the original item will be executed,
32
+ # then the macro will be encountered, and this process will repeat.
33
+ #
34
+ # note: if the +popped_item+ itself manipulates the +:exec+ stack, "complicated behavior" may arise
35
+ #
36
+ # *needs:* ExecDoTimesInstruction must be active; 2 +:int+ items, 1 +:exec+ item
37
+ #
38
+ # *pushes:* well, it's complicated...
39
+ #
2
40
 
3
41
  class CodeDoTimesInstruction < Instruction
4
42
  def preconditions?
@@ -1,3 +1,10 @@
1
+ # makes and pushes a clone of the top item on the +:code+ stack
2
+ #
3
+ # *needs:* 1 +:code+
4
+ #
5
+ # *pushes:* 1 +:code+
6
+ #
7
+
1
8
  class CodeDuplicateInstruction < Instruction
2
9
  include DuplicateInstruction
3
10
  def initialize(context)
@@ -1,3 +1,12 @@
1
+ # pops the top 2 items of the +:code+ stack;
2
+ # pushes a new ValuePoint onto the +:bool+ stack, with value +true+ if the
3
+ # two items' blueprint strings are identical
4
+ #
5
+ # *needs:* 2 +:code+
6
+ #
7
+ # *pushes:* 1 +:bool+
8
+ #
9
+
1
10
  class CodeEqualQInstruction < Instruction
2
11
  def preconditions?
3
12
  needs :code, 2
@@ -1,3 +1,10 @@
1
+ # pops the top item from the +:code+ stack;
2
+ # pushes it onto the +:exec+ stack so it is executed
3
+ #
4
+ # *needs:* 1 +:code+
5
+ #
6
+ # *pushes:* 1 +:exec+
7
+
1
8
  class CodeExecuteInstruction < Instruction
2
9
  def preconditions?
3
10
  needs :code, 1
@@ -1,3 +1,12 @@
1
+ # peeks at the top item from the +:code+ stack (without popping it!);
2
+ # pushes a new block containing that code value and "do code_pop" onto the +:exec+ stack,
3
+ # so the item is executed, then removed from the +:code+ stack
4
+ #
5
+ # *needs:* 1 +:code+
6
+ #
7
+ # *pushes:* 1 +:exec+
8
+ #
9
+
1
10
  class CodeExecuteThenPopInstruction < Instruction
2
11
  def preconditions?
3
12
  needs CodePopInstruction
@@ -1,3 +1,6 @@
1
+ # deletes all items from the +:code+ stack
2
+ #
3
+
1
4
  class CodeFlushInstruction < Instruction
2
5
  include FlushInstruction
3
6
  def initialize(context)
@@ -1,6 +1,14 @@
1
- # ORIGINAL PUSH3 DESCRIPTION: Pushes the result of substituting the third item on the code stack for the second item in the first item. As of this writing this is implemented only in the Lisp implementation, within which it relies on the Lisp "subst" function. As such, there are several problematic possibilities; for example "dotted-lists" can result in certain cases with empty-list arguments. If any of these problematic possibilities occurs the stack is left unchanged.
2
-
3
- # Here, we will pop three :code items, find all occurrences of the appropriate point in the changed codeblock, and then replace them in last-to-first order (so the point counts discovered initially don't change during substitution)
1
+ # pops three items from the +:code+ stack: the "host", the "old_subtree" and the "new_subtree";
2
+ # pushes a new +:code+ item which contants the +host+, with every occurrence of the +old_subtree+
3
+ # (if any) replaced by the +new_subtree+
4
+ #
5
+ # note: the order of arguments counts; the top +:code+ stack item is the +host+,
6
+ # the second is the +old_subtree+, and the third is the +new_subtree+
7
+ #
8
+ # *needs:* 3 +:code+
9
+ #
10
+ # *pushes:* 1 +:code+
11
+ #
4
12
 
5
13
  class CodeGsubInstruction < Instruction # was CODE.SUBST in Push3
6
14
  def preconditions?
@@ -1,3 +1,11 @@
1
+ # pops the top 2 items of the +:code+ stack, and one +:bool+;
2
+ # returns the top +:code+ item if the +:bool+ is +false+, the second one if +true+
3
+ #
4
+ # *needs:* 2 +:code+, 1 +:bool+
5
+ #
6
+ # *pushes:* 1 +:code+
7
+ #
8
+
1
9
  class CodeIfInstruction < Instruction
2
10
 
3
11
  def preconditions?
@@ -1,14 +1,26 @@
1
+ # pushes a new +:code+ item whose value is a block containing one call to every
2
+ # Instruction active in the context
3
+ #
4
+ # note: the order of instructions is determined by the order they appear in the context's library
5
+ #
6
+ # *needs:* nothing
7
+ #
8
+ # *pushes:* 1 +:code+
9
+
1
10
  class CodeInstructionsInstruction < Instruction
2
11
  def preconditions?
3
12
  true
4
13
  end
14
+
5
15
  def setup
6
16
  end
17
+
7
18
  def derive
8
19
  all_instructions = @context.instructions
9
20
  list_as_block = all_instructions.inject("block {") {|b,i| b + " do #{i.to_nudgecode}"} + "}"
10
21
  @result = ValuePoint.new("code", list_as_block)
11
22
  end
23
+
12
24
  def cleanup
13
25
  pushes :code, @result
14
26
  end
@@ -1,3 +1,13 @@
1
+ # pops the top 2 items from the +:code+ stack;
2
+ # pushes a new +:code+ item containing a block obtained by combining the other listings into one block
3
+ #
4
+ # note: the top stack item (the "attachment") is the second item of the resulting list
5
+ #
6
+ # *needs:* 2 +:code+
7
+ #
8
+ # *pushes:* 1 +:code+
9
+ #
10
+
1
11
  class CodeListInstruction < Instruction
2
12
  def preconditions?
3
13
  needs :code, 2
@@ -1,3 +1,17 @@
1
+ # pops the top 2 item of the +:code+ stack;
2
+ # pushes a new ValuePoint onto the +:bool+ stack, with value +true+ if the
3
+ # second argument appears as a block in the _backbone_ of the first argument
4
+ #
5
+ # note: order matters, and the top stack item is the second argument, the second stack item is the first
6
+ #
7
+ # note: compare to CodeContainsQInstruction, which checks for matches at all subtrees, not just the "root"
8
+ #
9
+ # *needs:* 2 +:code+
10
+ #
11
+ # *pushes:* 1 +:bool+
12
+ #
13
+
14
+
1
15
  class CodeMemberQInstruction < Instruction
2
16
  def preconditions?
3
17
  needs :code, 2
@@ -1,3 +1,13 @@
1
+ # pops the top +:name+ item;
2
+ # pushes a new +:code+ item that has a value equal to the current context binding
3
+ #
4
+ # note: if there is no binding, the resulting +:code+ value will be an empty string
5
+ #
6
+ # *needs:* 1 +:name+
7
+ #
8
+ # *pushes:* 1 +:code+
9
+ #
10
+
1
11
  class CodeNameLookupInstruction < Instruction # was Push3 CODE.DEFINITION
2
12
  def preconditions?
3
13
  needs :name, 1
@@ -1,3 +1,6 @@
1
+ # does nothing
2
+ #
3
+
1
4
  class CodeNoopInstruction < Instruction
2
5
  def preconditions?
3
6
  true
@@ -1,3 +1,15 @@
1
+ # pops the top +:code+ item and +:int+ item ("N");
2
+ # pushes a new +:code+ item containing the Nth backbone element of the +:code+, if it's a block
3
+ #
4
+ # If the +:code+ is not a block, it's replaced intact;
5
+ # if the +:code+ is an empty block, an +:error+ is pushed instead of a +:code+ item;
6
+ # otherwise, the index is chosen as +N+ modulo the length of the block's backbone.
7
+ #
8
+ # *needs:* 1 +:code+ and 1 +:int+
9
+ #
10
+ # *pushes:* 1 +:code+
11
+ #
12
+
1
13
  class CodeNthInstruction < Instruction
2
14
  def preconditions?
3
15
  needs :int, 1
@@ -1,3 +1,15 @@
1
+ # pops the top +:code+ item and +:int+ item ("N");
2
+ # pushes a new +:code+ item, which is the result of removing the first +N+ backbone elements of the +:code+
3
+ #
4
+ # If the +:code+ is not a block, it is wrapped in one first;
5
+ # if +N+ is less than 1, the original code (or newly wrapped atom) is returned;
6
+ # otherwise, the number of items removed is actually the backbone length *modulo* +N+
7
+ #
8
+ # *needs:* 1 +:code+, 1 +:int+
9
+ #
10
+ # *pushes:* 1 +:code+
11
+ #
12
+
1
13
  class CodeNthCdrInstruction < Instruction
2
14
  def preconditions?
3
15
  needs :int, 1
@@ -17,10 +29,10 @@ class CodeNthCdrInstruction < Instruction
17
29
  if b_len > 0
18
30
  new_tree = CodeblockPoint.new(backbone.contents.slice(@arg1 % b_len, b_len))
19
31
  else
20
- new_tree = CodeblockPoint.new([])
32
+ new_tree = backbone
21
33
  end
22
34
  else
23
- new_tree = @arg1 > 0 ? CodeblockPoint.new([tree.linked_code]) : CodeblockPoint.new([])
35
+ new_tree = @arg1 < 1 ? CodeblockPoint.new([tree.linked_code]) : CodeblockPoint.new([])
24
36
  end
25
37
  @result = ValuePoint.new("code", new_tree.blueprint)
26
38
  end
@@ -1,12 +1,26 @@
1
+ # pops the top +:code+ item and +:int+ item ("N");
2
+ # pushes a new +:code+ item containing the Nth program point of the +:code+
3
+ #
4
+ # If the +:code+ is not a block, it's replaced intact;
5
+ # if the +:code+ value cannot be parsed, an +:error+ is pushed instead of a +:code+ item;
6
+ # otherwise, the index is chosen as +N+ modulo the length of the number of program points.
7
+ #
8
+ # *needs:* 1 +:code+ and 1 +:int+
9
+ #
10
+ # *pushes:* 1 +:code+
11
+ #
12
+
1
13
  class CodeNthPointInstruction < Instruction # was CODE.EXTRACT in Push3
2
14
  def preconditions?
3
15
  needs :int, 1
4
16
  needs :code, 1
5
17
  end
18
+
6
19
  def setup
7
20
  @arg1 = @context.pop_value(:int)
8
21
  @arg2 = @context.pop_value(:code)
9
22
  end
23
+
10
24
  def derive
11
25
  tree = NudgeProgram.new(@arg2)
12
26
  tree_size = tree.points
@@ -15,6 +29,7 @@ class CodeNthPointInstruction < Instruction # was CODE.EXTRACT in Push3
15
29
  pt = tree[which]
16
30
  @result = ValuePoint.new("code", pt.blueprint)
17
31
  end
32
+
18
33
  def cleanup
19
34
  pushes :code, @result
20
35
  end
@@ -1,14 +1,25 @@
1
+ # pops the top +:code+ item;
2
+ # pushes a new +:bool+ item with value +true+ if the +:code+ is an empty block
3
+ #
4
+ # *needs:* 1 +:code+
5
+ #
6
+ # *pushes:* 1 +:bool+
7
+ #
8
+
1
9
  class CodeNullQInstruction < Instruction
2
10
  def preconditions?
3
11
  needs :code, 1
4
12
  end
13
+
5
14
  def setup
6
15
  arg_blueprint = @context.pop_value(:code)
7
16
  @arg1 = NudgeProgram.new(arg_blueprint).blueprint
8
17
  end
18
+
9
19
  def derive
10
20
  @result = ValuePoint.new("bool", @arg1 == "block {}")
11
21
  end
22
+
12
23
  def cleanup
13
24
  pushes :bool, @result
14
25
  end
@@ -1,3 +1,11 @@
1
+ # pops the top +:code+ item;
2
+ # pushes a new +:bool+ with value +true+ if the +:code+ can be parsed
3
+ #
4
+ # *needs:* 1 +:code+
5
+ #
6
+ # *pushes:* 1 +:bool+
7
+ #
8
+
1
9
  class CodeParsesQInstruction < Instruction
2
10
  def preconditions?
3
11
  needs :code, 1
@@ -1,3 +1,11 @@
1
+ # pops the top +:code+ item;
2
+ # pushes a new +:int+ with the number of program points in the +:code+
3
+ #
4
+ # *needs:* 1 +:code+
5
+ #
6
+ # *pushes:* 1 +:int+
7
+ #
8
+
1
9
  class CodePointsInstruction < Instruction
2
10
 
3
11
  def preconditions?
@@ -1,3 +1,6 @@
1
+ # pops (and discards) the topmost item from the +:code+ stack
2
+ #
3
+
1
4
  class CodePopInstruction < Instruction
2
5
  include PopInstruction
3
6
  def initialize(context)
@@ -1,3 +1,14 @@
1
+ # pops the top two +:code+ items;
2
+ # pushes a new +:int+ item, with value equal to the program point number in the first argument
3
+ # where the second argument appears as a subtree (or 0 otherwise)
4
+ #
5
+ # note: order of arguments is important; the top stack item is the second argument
6
+ #
7
+ # *needs:* 2 +:code+
8
+ #
9
+ # *pushes:* 1 +:int+
10
+ #
11
+
1
12
  class CodePositionInstruction < Instruction
2
13
  def preconditions?
3
14
  needs :code, 2