OP_PLACE
login
{ "title": "OP_PLACE", "related": ["op_pick.md"] }

OP_PLACE

Copies a stack item to another position

Syntax and Stack

item count OP_PLACE => item?

  • item: the item copied
  • count: how far back to count. Count 0 is item.

Binary representation

OP_PLACE is defined as the single byte 0xe9.

Operation

This opcode is the inverse of OP_PICK. When combined with pick, it allows stack items to be essentially used as RAM locations – script authors or compilers can implement read-modify-write semantics on “variables” that were previously bound to a stack position.

For example, the following diagram shows how OP_PICK and OP_PLACE are used to grab two “variable” from deep in the stack, add them, overwrite one variable and use the result. In pseudo-code:

B = A + B
if (B != 0) ...

If A is located 10 below the stack top, and B 5 below, the BCH script would look like:

10 PICK 6 PICK ADD 6 PLACE IF ... ENDIF
Deep StackActive StackGrab the variables10 PICK6 PICKADDoverwrite B5 PLACEUse the sum...OP_IFDeep StackActive Stack

count must be a BigNum, CScriptNum, or little-endian encoded sign-magnitude number (T.O1). count is popped from the stack. The BMD is not applied during this operation (T.0.8).

Indexing backwards

If count is positive, fail if the stack is <= count (T.O2). Otherwise, set stack item[stack length - 1 - count] to item, assuming zero-based array indexing (T.O3). For clarity, if count == 0, this opcode overwrites item with itself.

Indexing forwards

If count is < 0 (treat -0 as 0: T.O4), set stack item[abs(count)-1] to item (T.O5). Fail if abs(count) > stack length (T.O6).

Note that item MUST be popped from the stack before any stack length checks are made (T.O7).

Design considerations

Bidirectional Indexing

In some scripts or situations it may be simpler to count forward from the beginning of the stack. Access in this manner is analogous to using “global variables”. However, doing so for “local variables” would complicate macro instantiation since one would need to identify the stack depth at compile or runtime to properly index items.

Given two different access semantics, it makes sense to have two different access methods.

Note that it may be desired to pass the index of a “local variable” into the instantiation of a macro (effectively passing a pointer to that variable to the macro). To accomplish this elegantly, one would need an opcode that return the current stack length. However, to avoid this opcode, it is possible to pass the local variable’s current stack depth, and have the macro add its stack usage. Or use N OP_PICK to place the variable on the stack top (essentially pass-by-value), instantiate the macro, and use N OP_PLACE OP_DROP to copy it back.

Indexing Direction

The indexing direction was chosen to be compatible with OP_PICK.