# "here" control

The unit at [mem/here.fs] helps controlling the "here" value in two ways: here
override and here locking.

## Overriding here

A lot of words in Forth play around "here" and sometimes, we'd like to use them
in memory areas that aren't here. For example, one could want to assemble a
binary in a pre-allocated area of memory and use words like "," and "allot" as
if we were naively assembling to here. But because the area is pre-allocated,
here is already past it!

This unit provides "here[ ( newhere -- oldhere )" and "]here ( oldhere -- )" as
a way to temporarily override here. Example usage:

  create foo 100 allot
  foo here[ ," hello!" ]here

This code will write "hello" at the beginning of "foo" rather than after it.

"here[" and "]here" pairs can be nested, but they of course have to be balanced.
If you abort in the middle of such pair, you can call "here$" to reset here
status.

### Real here

This unit, upon a top level "here[" call, remembers the "real" here. It's used
in "here$" to restore it, but it can be useful in some cases to have access to
this value, for example in allocators [doc/mem/alloc]. When allocators need to
allocate permanent memory, they will never want to allocate them in the
overridden here, always in the "real" one.

For this purpose, we have the "realhere ( -- a )" and "realallot ( n -- )" words
which access the "real" here regardless of "here[ / ]here" status.

## Locking here

There are cases where you're writing stuff to here which needs to stay
contiguous at the same time as you're using words which might, or might not use
dynamic allocation mechanism in a way that will result in an allocation to here
that conflicts with your current work.

This will generally corrupt your memory and cause bugs that are difficult to
identify.

To protect yourself from bugs that are difficult to pinpoint, you can "lock
here" before you begin your operation. Then, any dynamic allocator that is about
to allocate to here will check the lock and abort if it's taken.

The purpose of this mechanism isn't really to prevent corruption, only to detect
logic errors that lead to corruption by aborting explicitly.

## API

here$ ( -- )
  Reset here locking and override status. Restore "real" here if needed.
lockhere ( -- )
  Take the lock.
unlockhere ( -- )
  Release the lock.
herefree# ( -- )
  If the lock is taken, abort with message.
here[ ( newhere -- oldhere )
  Override here with address "newhere".
]here ( oldhere -- )
  Restore here to "oldhere".
