# LFL and LFU — LIFO Stack

Source: https://rungs.dev/docs/ladder-logic/instructions/lfl-lfu

> LFL and LFU in rungs.dev build a last-in first-out stack in an array — push a value on top, take the newest one back off. Use them for undo histories and nesting.

Puts a value on top of a stack on each rising edge, and stops once the stack holds .LEN of them.

Takes the newest value off the top of a stack on each rising edge, leaving the others where they are.

## What a LIFO is [#what-a-lifo-is]

**LIFO** means _last in, first out_ — a stack, like a pile of plates. The last value you put on
is the first one you take back off.

Reach for a stack when the most recent thing matters most: the last alarm raised, the step you
were on before this one, an undo history.

`LFL` and `LFU` are the [`FFL` and `FFU`](https://rungs.dev/docs/ladder-logic/instructions/ffl-ffu) of a stack. Everything about them is the
same — the operands, the rising edge, the shared [`CONTROL`](https://rungs.dev/docs/ladder-logic/instructions/array-instructions#control-tag-members)
tag, `.DN` for full and `.EM` for empty — except **which element the unload takes**.

## Operands [#operands]

### LFL [#lfl]

| Name       | Type      | Notes                                        |
| ---------- | --------- | -------------------------------------------- |
| `source`   | numeric   | The value to push on. A tag or a number      |
| `array`    | numeric[] | Where the stack starts — `Buf` or `Buf[2]`   |
| `control`  | `CONTROL` | The stack's state                            |
| `length`   | number    | How many slots the stack has                 |
| `position` | number    | How many are in use at start-up. Usually `0` |

### LFU [#lfu]

| Name          | Type      | Notes                               |
| ------------- | --------- | ----------------------------------- |
| `array`       | numeric[] | Where the stack starts              |
| `destination` | numeric   | Where the popped value goes         |
| `control`     | `CONTROL` | The same control tag the `LFL` uses |
| `length`      | number    | Same as the `LFL`'s                 |
| `position`    | number    | Same as the `LFL`'s                 |

The array can be `DINT`, `INT`, `SINT` or `REAL`, and a value of a different type converts on
the way in and out.

## How It Works [#how-it-works]

`LFL` is `FFL` exactly: it writes at `.POS` and moves `.POS` up one.

`LFU` differs in one line. Where `FFU` takes the element at the **start** and shifts everything
down, `LFU` takes the element at `.POS - 1` — the top of the stack — zeroes that slot, and
leaves every other element where it is.

| Instruction | Takes the element at | Shifts the others? |
| ----------- | -------------------- | ------------------ |
| `FFU`       | the start            | Yes, down one      |
| `LFU`       | `.POS - 1`           | No                 |

That is the whole difference, and it is why `LFU` is the faster of the two on a long buffer:
it moves one element instead of all of them.

## Example — Last Alarm First [#example--last-alarm-first]

Every alarm is pushed on; `Acknowledge` clears the newest one first.

```ladder
XIC(AlarmRaised)LFL(AlarmCode,Stack,SCtl,?,?);XIC(Acknowledge)LFU(Stack,TopAlarm,SCtl,?,?);XIC(SCtl.EM)OTE(AllClear)

SCtl.LEN = 8
SCtl.POS = 0
```

## Common Mistakes [#common-mistakes]

- Expecting `LFU` to shift the array. It does not — only the element it took is cleared.
- Mixing a `LFL` with an `FFU` on one control tag. That is a queue and a stack disagreeing
  about which end is which.
- Everything on the [`FFL` and `FFU` list](https://rungs.dev/docs/ladder-logic/instructions/ffl-ffu#common-mistakes) applies here too.

## Related [#related]

- [FFL and FFU](https://rungs.dev/docs/ladder-logic/instructions/ffl-ffu) — a queue instead of a stack
- [Array instructions overview](https://rungs.dev/docs/ladder-logic/instructions/array-instructions) — the `CONTROL` members
- [RES](https://rungs.dev/docs/ladder-logic/instructions/res) — empties the stack by clearing `.POS`