# Push Instruction Documentation

**URL:** <https://discourse.pushlanguage.org/t/push-instruction-documentation/2185>\
**Category:** Orientation\
**Created:** [February 22, 2023, 3:25am UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185 "2023-02-22T03:25:54Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![erp12](https://avatars.discourse-cdn.com/v4/letter/e/f475e1/32.png) [@erp12](https://discourse.pushlanguage.org/u/erp12)\
**Post date:** [February 22, 2023, 3:25am UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/1 "2023-02-22T03:25:54Z")

</div>

Some Push instructions are trickier to understand than others, especially the ones that implement looping/control flow. This wiki page documents the non-trivial instructions found in modern Push implementations with the hopes of making it easier to implement comparable PushGP systems.

> For people using [Clojush](https://github.com/lspector/Clojush) as their reference implementation, there is also the [clojush-playground](https://github.com/erp12/clojush-playground/blob/main/README.md) project which provides REPL friendly utilities for testing out instructions.

Each section is dedicated to an individual instruction. It includes a description of that instruction’s logic in prose, some rationale for why the instruction should be used, the conditions under which it should NOOP, and some example “before and after” stacks to demonstrate the behavior.

Each “before and after” (B&A) stacks two EDN maps. The top of the stack being the first item in the list (furtherest to the left).

**Contributing:**

To add documentation of a specific instruction, copy an existing section and populate each section. When coming up with “before and after” stacks, it is helpful to include a base case and any edge cases.

The following should **NOT** be considered edge cases that need documenting.

- Meeting any of the listed NOOP conditions.
- Reaching interpreter limits, such as step limit or stack depth limits.
- Any non-standard interpreter modes or evolutionary features. (ie. epigenetics)

## `code_do_then_pop`

Pushes a `code_pop` instruction and the top item of the `code` stack to the `exec` stack. Does not consume the top item from the `code` stack.

Assumes the `code_pop` is an instruction which pops the top item off the code stack.

**Rationale:**

Used to perform the top `code` item before it is removed from the `code` stack. This can be used to implement recursive behavior if the top `code` item manipulates the `code` stack.

**NOOP Conditions:**

- Empty `code` stack.

**B&A: Base case**

```clojure
{
    :int ()
    :code (1)
    :exec ()
}
{
    :int ()
    :code (1)
    :exec (1 code_pop)
}

```

**B&A: Recursion**

Assuming `code_dup` in an instruction will duplicate the top item of the code stack, executing the `code_do_then_pop` instruction with the following stack will result in an infinite loop producing `1` values on the `:int` stack.

```clojure
{
    :int ()
    :code ((code_dup 1))
    :exec ()
}
{
    :int ()
    :code ((code_dup 1))
    :exec ((code_dup 1) code_pop)
}

```

## `code_do_range`

Evaluates the top item on the `code` stack for each step along the range `i` to `j`.  
Both `i` and `j` are taken from the int stack.

**Rationale:**

Implements a loop where the “body” is taken from the `code` stack.

**NOOP Conditions:**

- Empty `code` stack.
- Fewer than 2 items on the `int` stack.

**B&A: Counting up**

Loop counter is `2` and loop will stop at `5`.

> Question: Why is the current loop index put on the `:int` stack each iteration?

```clojure
{
    :int (5 2)
    :code ("A")
    :exec ()
}
{
    :int (2)
    :code ()
    :exec ("A" (3 5 code_from_exec "A" code_do_range))
}

```

**B&A: Counting down**

Loop counter is `2` and loop will stop at `0`.

```clojure
{
    :int (0 2)
    :code ("A")
    :exec ()
}
{
    :int (2)
    :code ()
    :exec ("A" (1 0 code_from_exec "A" code_do_range))
}

```

**B&A: Exit loop**

Loop stops at the current iteration (counter and termination at `2`).

```clojure
{
    :int (2 2)
    :code ("A")
    :exec ()
}
{
    :int (2)
    :code ()
    :exec ("A")
}

```

# Undocumented

- `exec_do_range`
- `code_do_count`
- `exec_do_count`
- `code_do_times`
- `exec_do_times`
- `exec_while`
- `exec_do_while`
- `code_map`
- `code_if`
- `exec_if`
- `code_when`
- `exec_when`
- Add more to the list

---

<div class="post-metadata">

**Author:** ![erp12](https://avatars.discourse-cdn.com/v4/letter/e/f475e1/32.png) [@erp12](https://discourse.pushlanguage.org/u/erp12)\
**Post date:** [February 22, 2023, 3:27am UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/2 "2023-02-22T03:27:17Z")

</div>

@lspector Do you think this wiki belongs in #orientation?

---

<div class="post-metadata">

**Author:** ![lspector](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.pushlanguage.org/lspector/32/4_2.png) [@lspector](https://discourse.pushlanguage.org/u/lspector)\
**Post date:** [February 22, 2023, 6:34pm UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/3 "2023-02-22T18:34:17Z")

</div>

Yes, I think that’s a great place for it.

My only very minor reservation with this whole thing is that the sections don’t include a name for the actual instruction, just an English label like “Code Do Range.” I realize this is probably intentional because the actual instruction names will vary among implementations, but it’s a little confusing/abstract especially with labels like “Code Do Then Pop,” which may cause the reader to think “wait, what?, is that an instruction?” Maybe we could add an example actual name that would make it more clear, like “(example: `code_do_then_pop` in PyshGP)”?

---

<div class="post-metadata">

**Author:** ![mcphee](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.pushlanguage.org/mcphee/32/3_2.png) [@mcphee](https://discourse.pushlanguage.org/u/mcphee)\
**Post date:** [February 25, 2023, 4:17am UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/4 "2023-02-25T04:17:06Z")

</div>

Do we need to document both the `code_` and `exec_` versions? Most users of a Push system will never use the `code` stack; none of the problems in either benchmark suite use them, for example.

At a minimum, I’d start by documenting the `exec_` instructions, and then maybe do the `code_` instructions in a separate, but related document.

I also think there’s a discussion to be had (perhaps in a different topic) about what’s the “right” thing to do when, e.g., something like `exec_if` no-ops. At the moment if there’s not a value on the boolean stack (in both Clojush and Propeller, at least), then `exec_if` no-ops and _both_ the `then` and `else` blocks are left on the `exec` stack. I’m not actually convinced that’s a good idea, but I’ve never experimented with it to see. Since those blocks are fundamentally connected to the `exec_if` (they only exist as blocks because of the way we convert `exec_if` from the Plushy genome to a Push program), it seems to me that it might make more sense to remove them from the `exec` stack as well. As I said, I’ve never experimented with this, but this is a place where I’m not sure I’d want to “bake in” that notion of no-op before someone has looked into its impact.

I can say that I’ve seen some infinite-loop programs that did some weird things with no-oping `exec` instructions, which made me wonder if we’re really doing the “best” thing here.

---

<div class="post-metadata">

**Author:** ![erp12](https://avatars.discourse-cdn.com/v4/letter/e/f475e1/32.png) [@erp12](https://discourse.pushlanguage.org/u/erp12)\
**Post date:** [April 14, 2023, 6:31pm UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/5 "2023-04-14T18:31:16Z")

</div>

I just published a tiny library for testing out Clojush instructions in the REPL without needed access to a copy of the Clojush project source code.

It can be pointed to any version of Clojush (in a `deps.edn` or `clj` command) but you can try it out against the most recent Clojush version in Clojars in a REPL with this 1 liner:

```plaintext
clj -Sdeps '{:deps {clojush/clojush {:mvn/version "LATEST" :exclusions [bouncycastle/bctsp-jdk14]} io.github.erp12/clojush-playground {:git/sha "72deacfe157da2134878ed4702a861e1ebc8bcda"}}}'

```

Then mess around with trying different instructions on different states:

```clojure
(require '[erp12.clojush-playground.core :as play])

(play/exercise-instruction-1
  'exec_do*count
  {:integer (list 3)
   :exec (list true)
   :boolean (list)})
;; {:integer (), :exec ((0 2 exec_do*range true)), :boolean ()}

```

Paired with reading the Clojush source code, hopefully this can help demystify what some of these instructions are doing. Ideally, we would still capture the rationale for some of the wackier instruction in prose here in this thread. More information about the playground’s functionality can be found in the README on GitHub.

> **[GitHub - erp12/clojush-playground: Utilities for exploring how Clojush is...](https://github.com/erp12/clojush-playground)**
>
> Utilities for exploring how Clojush is implemented - GitHub - erp12/clojush-playground: Utilities for exploring how Clojush is implemented

---

<div class="post-metadata">

**Author:** ![mcphee](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.pushlanguage.org/mcphee/32/3_2.png) [@mcphee](https://discourse.pushlanguage.org/u/mcphee)\
**Post date:** [April 14, 2023, 9:38pm UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/6 "2023-04-14T21:38:14Z")

</div>

Is this an argument for at least pulling the Push interpreter out of either Clojush or Propeller and have the as stand-alone projects that the others depend on? Then, for example, we wouldn’t have all these questions about whether Clojush and Propeller “do the same thing”?

---

<div class="post-metadata">

**Author:** ![bill](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.pushlanguage.org/bill/32/6_2.png) [@bill](https://discourse.pushlanguage.org/u/bill)\
**Post date:** [April 14, 2023, 10:23pm UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/7 "2023-04-14T22:23:37Z")

</div>

> [@mcphee](#):
>
> s this an argument for at least pulling the Push interpreter out

/me clicks “heart” 100 times

---

<div class="post-metadata">

**Author:** ![erp12](https://avatars.discourse-cdn.com/v4/letter/e/f475e1/32.png) [@erp12](https://discourse.pushlanguage.org/u/erp12)\
**Post date:** [April 15, 2023, 2:21am UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/8 "2023-04-15T02:21:53Z")

</div>

> [@mcphee](#):
>
> Is this an argument for at least pulling the Push interpreter out of either Clojush or Propeller and have the as stand-alone projects that the others depend on?

For the end goal I have in mind, yes!

One subset of people who care about PushGP is those who are looking for an implementation of _the_ Push language which yielded the numbers in the tables of our papers. I think this subset would be well served by a single implementation that:

1. Provides the “standard” set of stacks, instructions, limits, and other program execution behaviors.
2. Allow programs to be represented by some reasonably generic data structure that could be produced in their own systems.
3. Is callable from wide range of runtimes. (ie. not just JVM)
4. runs roughly as fast as a Turing complete stack-machine interpreter can be expected to.

That said, there is another (smaller) subset of people who care about PushGP that will want to use as an inductive program synthesis system for their domain. These people care about adding custom stacks, instructions, and other extensions. I would imagine this would be difficult to provide in a single “standard” implementation.

---

<div class="post-metadata">

**Author:** ![erp12](https://avatars.discourse-cdn.com/v4/letter/e/f475e1/32.png) [@erp12](https://discourse.pushlanguage.org/u/erp12)\
**Post date:** [April 17, 2023, 12:43am UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/9 "2023-04-17T00:43:42Z")

</div>

Does anyone know the story behind the `code_map` instruction from Clojush? I have been starting at the code and running some simple states through it, but so far bit able to understand the purpose of the instruction.

> <https://github.com/lspector/Clojush/blob/master/src/clojush/instructions/code.clj#L231-L247>

Furthermore, I don’t think this instruction comes up much in our discussions. Do we use it other systems like Propeller? Do we often include it in our problem definitions? If so, does it end up in solutions for some problems?

---

<div class="post-metadata">

**Author:** ![lspector](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.pushlanguage.org/lspector/32/4_2.png) [@lspector](https://discourse.pushlanguage.org/u/lspector)\
**Post date:** [April 17, 2023, 3:27pm UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/10 "2023-04-17T15:27:17Z")

</div>

I can tell you the story (or I guess parts of what are probably several stories), although I’m not sure it does what was intended or it it’s useful as it is.

There was a `map` instruction in the first versions of Push, which was intended to roughly mimic Common Lisp’s `mapcar` (roughly equivalent to Clojure’s `map`), with both the function and the list over which it is mapped taken from the `code` stack or possibly the `child` stack, which also contained code. Recall that at this point there was no `exec` stack. FWIW here’s the underlying Common Lisp implementation from the [first version of Push](https://faculty.hampshire.edu/lspector/pushgp/push.lisp), written in terms of any type, but I think it was only ever built into `code` and maybe `child` instructions:

```auto
(defun &map (type)
  "Treats the item on top of the stack of the given type as a
list (coercing it to a list if necessary) and the second element 
as a body of code to apply iteratively to each element of the list.
The arguments are both popped prior to the recursive evaluations.
The results are collected and pushed as a list."
  (unless (null (rest (pushtype-stack type)))
    (let ((the-list (ensure-list (first (pushtype-stack type))))
          (the-code (second (pushtype-stack type))))
      ;; clear the args
      (pop (pushtype-stack type))
      (pop (pushtype-stack type))
      ;; do the mapping
      (let ((results nil))
        (dolist (item the-list)
          (push item (pushtype-stack type))
          (evalpush the-code)
          ;; extract, save, and remove the result
          (push (first (pushtype-stack type)) results)
          (pop (pushtype-stack type))
          (when (> (count-points results) ;; escape if result is bloating
                   *max-points-in-program*)
            (return nil)))
        (unless (> (count-points results)
                   *max-points-in-program*)
          (push (reverse (copy-tree results))
                (pushtype-stack type)))))))

```

Note that although this looks sort of like Clojure, it relies on destructive modification (mutation). Also, because there was no `exec` stack, it couldn’t work as modern Push looping/recursive/combinator instructions do, pushing the next things to do onto the `exec` stack for processing in a later cycle. Rather, it recursively invoked the top-level `evalpush` function, running each function/argument combo in a fresh interpreter. Then it collected all of the results and pushed a list of them back onto the stack in the interpreter that ran `map`.

So this was an attempt to do something like mapping in the Push context, with both the function and the arguments coming from stacks. It was pretty weird, among other reasons because the “function” may not have been anything like a function. But with the right things in the right places it could indeed achieve a `map`-like effect.

When the `exec` stack came along, in Push3, I think we first dropped this `map` idea entirely, in favor of `do`-style loops like `exec.do*count`, which were implemented both for the `code` and the `exec` stacks. We also added the combinators. At least that’s what I see from [the Scheme implementation](https://faculty.hampshire.edu/lspector/schush.ss).

At some point we must have added `map` and maybe some other things back in to Clojush, but I think only for `code`. I’m not sure that we did it correctly/well, or if we ever used it, and I think most of our work has not used the `code` instructions at all. I guess maybe it was used for some (but not all) autoconstruction work, and maybe in “kitchen sink” configurations, etc., but I think mostly we’ve just relied on `exec` for everything that’s code-like. We _have_ discussed implementing `exec_map` and maybe some other higher-order functions in recent discussions of rethinking Push’s iteration/recursion facilities, but I don’t think this has yet gotten very far. And I think that GPT3 used `exec_map` once when I asked it to write a Push program! But I don’t think we have it yet.

Although I haven’t fully traced through the `code_map` code above, I do think that a key is probably that the `code_wrap` and `code_cons` are being used to assemble the list of all of the results.

---

<div class="post-metadata">

**Author:** ![erp12](https://avatars.discourse-cdn.com/v4/letter/e/f475e1/32.png) [@erp12](https://discourse.pushlanguage.org/u/erp12)\
**Post date:** [April 20, 2023, 5:50pm UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/11 "2023-04-20T17:50:07Z")

</div>

Very interesting and helpful! Thanks @lspector

With that history in mind and @mcphee’s comment here

> [@mcphee](#):
>
> Do we need to document both the `code_` and `exec_` versions? Most users of a Push system will never use the `code` stack; none of the problems in either benchmark suite use them, for example.

I wonder if it would be acceptable (at least in pyshgp) to not implement any of the code instructinos.

FWIW, I did a search in Clojush problem files within the `software/` folder and found [a couple of problems that do use the `:code` stack](https://github.com/search?q=repo%3Alspector%2FClojush+%3Acode+path%3A%2F%5Esrc%5C%2Fclojush%5C%2Fproblems%5C%2F%2F+path%3A%2F%5Esrc%5C%2Fclojush%5C%2Fproblems%5C%2Fsoftware%5C%2F%2F&type=code) but they are problems which I typically don’t run.

---

<div class="post-metadata">

**Author:** ![bill](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.pushlanguage.org/bill/32/6_2.png) [@bill](https://discourse.pushlanguage.org/u/bill)\
**Post date:** [April 20, 2023, 6:29pm UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/12 "2023-04-20T18:29:02Z")

</div>

> [@erp12](#):
>
> I wonder if it would be acceptable (at least in pyshgp) to not implement any of the code instructinos.

I suppose the research question is whether `:code` instructions aren’t used in programs because they were never added to the problem definitions to begin with, or whether they are not needed to solve problems in a useful and interesting way.

“We don’t see them in evolved solutions” carries a lot of water for the implicit ways in which problems have been selected, especially when there are no local variables or saved states like `:environment`, too.

But if `:exec` can do the work, and produce programs that don’t make you wince when you read the source code…

---

<div class="post-metadata">

**Author:** ![erp12](https://avatars.discourse-cdn.com/v4/letter/e/f475e1/32.png) [@erp12](https://discourse.pushlanguage.org/u/erp12)\
**Post date:** [April 24, 2023, 8:23pm UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/13 "2023-04-24T20:23:15Z")

</div>

Is there a difference between the `string_contains` instruction and the `string_includes` instruction in Clojush? Unless I am missing something, the only thing I can spot is the order we pop the arguments off the stack.

> <https://github.com/lspector/Clojush/blob/master/src/clojush/instructions/string.clj#L218-L231>

> <https://github.com/lspector/Clojush/blob/master/src/clojush/instructions/string.clj#L436-L446>

---

<div class="post-metadata">

**Author:** ![lspector](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.pushlanguage.org/lspector/32/4_2.png) [@lspector](https://discourse.pushlanguage.org/u/lspector)\
**Post date:** [April 25, 2023, 1:46am UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/14 "2023-04-25T01:46:05Z")

</div>

> [@erp12](#):
>
> Is there a difference between the `string_contains` instruction and the `string_includes` instruction in Clojush?

It’s kind of funny how every code-level decision was made in opposite ways in the two implementations.

But it sure looks like they do the same thing.

I think we should get rid of `string_contains` since I think all of the decisions in it are worse (especially reliance on interop and the unnecessary `if`).

---

<div class="post-metadata">

**Author:** ![thelmuth](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.pushlanguage.org/thelmuth/32/2_2.png) [@thelmuth](https://discourse.pushlanguage.org/u/thelmuth)\
**Post date:** [May 6, 2023, 4:08pm UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/15 "2023-05-06T16:08:35Z")

</div>

It looks like my former student @pxkelly added `string_includes` when we were adding a bunch of new instructions for PSB2, and didn’t realize we already had this functionality. Feel free to delete either one.

---

<div class="post-metadata">

**Author:** ![lspector](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.pushlanguage.org/lspector/32/4_2.png) [@lspector](https://discourse.pushlanguage.org/u/lspector)\
**Post date:** [May 6, 2023, 5:05pm UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/16 "2023-05-06T17:05:00Z")

</div>

Done. I think I did it right… it has been a long time since I’ve committed a change to Clojush :). We’ll see if the automation does the right things…

---

<div class="post-metadata">

**Author:** ![erp12](https://avatars.discourse-cdn.com/v4/letter/e/f475e1/32.png) [@erp12](https://discourse.pushlanguage.org/u/erp12)\
**Post date:** [June 10, 2023, 7:42pm UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/17 "2023-06-10T19:42:19Z")

</div>

Does anyone who is up to date on the instruction sets used in modern PushGP publication results know if `exec_y` is typically used? My reading of the master branch of Clojush seems to imply the answer is yes.

I ask because I am seeing in pyshgp that more CPU time spent performing `exec_y` than all of parent selection combined, which seems like a red flag. I see some evidence that this instruction is causing a lot of stragglers in the population that hold up the entire generation.

If it’s important for finding solutions, I am fine with the cost. I somewhat recall discussions about `exec_y` being considered dangerous but I forget if that had to do with solution rates, non-termination, or something else. Anybody else remember? Mostly likely for @lspector @thelmuth @aks @mcphee

---

<div class="post-metadata">

**Author:** ![bill](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.pushlanguage.org/bill/32/6_2.png) [@bill](https://discourse.pushlanguage.org/u/bill)\
**Post date:** [June 10, 2023, 10:12pm UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/18 "2023-06-10T22:12:13Z")

</div>

Well by definition it makes the program running it non-terminating

---

<div class="post-metadata">

**Author:** ![lspector](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.pushlanguage.org/lspector/32/4_2.png) [@lspector](https://discourse.pushlanguage.org/u/lspector)\
**Post date:** [June 10, 2023, 11:12pm UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/19 "2023-06-10T23:12:50Z")

</div>

A program executing `exec_y` can terminate if something within the body can cause it to escape the loop. The most helpful versions of this probably involve `exec_if` and `exec_pop`, but there are other things you could do including `exec_flush`.

@thelmuth, @aks, and @mcphee probably have better memory than I do about what we’ve learned about `exec_y`’s benefits and dangers. I do recall that it shows up in solutions, but that doesn’t mean we wouldn’t solve problems without it.

FWIW, one of the GPTP papers this year was (in part) about benefits from reducing looping options, using recursion patterns that are all versions of fold and reduce, if I recall correctly.

---

<div class="post-metadata">

**Author:** ![thelmuth](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.pushlanguage.org/thelmuth/32/2_2.png) [@thelmuth](https://discourse.pushlanguage.org/u/thelmuth)\
**Post date:** [June 12, 2023, 1:13am UTC](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185/20 "2023-06-12T01:13:02Z")

</div>

Negative anecdotal evidence from @mcphee:

- [https://discourse.pushlanguage.org/t/next-autodog-experiments/358/64?u=thelmuth](https://discourse.pushlanguage.org/t/next-autodog-experiments/358/64)

Positive anecdotal evidence:

- I vaguely remember that when my students were working on adaptive genetic source, we found some data showing that `exec_y` was being used more than expected and in more useful programs. I just searched for a while here and couldn’t find that history.
- We’ve certainly seen `exec_y` used in _some_ solutions. Does that mean we’d find fewer solutions without it? No, it could certainly be the case that it’s still doing more harm than good.

The empiricist in me says we should just do some runs using `INSERT YOUR FAVORITE PUSHGP SYSTEM HERE` with and without it, and compare times and solution rates. If time is much higher with it and solution rates aren’t much higher (or are lower), then we should ditch it.

[Next page](https://discourse.pushlanguage.org/t/push-instruction-documentation/2185.md?page=2)
