# Big Moustache

*Tea for two and two for tea...*

Don't you think that the "{" character looks like a mustache? A whole lot of
them means a big moustache.

This library is a way of compiling fancy *and* fast memory accesses. The syntax
of such memory accesses is:

  <action>{<modifiers>}

For example, "@{c+4}" is the equivalent of "4 + c@", but compiled in efficient
HAL [doc/hal].

That generated HAL is really efficient and is the main reason why Big Moustache
exists. Sure, the syntactic sugar is nice, but it alone isn't worth it. All
those moustaches are really fast.

Not all actions/modifiers combinations make sense. When they don't, their usage
lead to undefined behavior. Incompatibilities are explicitly stated in the
documentation below. The rest is compatible.

Moustaches work fine under interpret mode, but they don't leverage the HAL, they
just "play" the moustache with regular words. They are therefore not faster.
Moreover, they cannot be used with modifiers "R F A".

## Target

We call "target" the address or value that the modifiers inside a moustache
designate. By default, and like the HAL does, targets contain a single level of
indirection.

For example, "{'data}" targets the memory at the address that the word "data"
will yield *at the moment the moustache is compiled*. "{}" targets the memory
pointed by the address in the W register *at runtime*. "{&}" targets the W
register directly.

### Managing W

There's a fundamental difference between W and non-W targets. Moustaches will
have a different signature depending on whether they target W or not.

For example, "@{}", which targets W and is the equivalent of a straight "@", has
the signature ( a -- n ). However, "@{R+4}", which targets RSP, has a signature
( -- n ). Similarly, "!{+4}" has a signature ( n a -- ) where "!{'foo}" has a
signature ( n -- ).

The principle is the same for all actions.

## Actions

Possible actions are:

  Access       @ ! @! @A @Ainc
  Arithmetics  + - -^ * / lshift rshift and or xor = <> < > <= >=
  Execution    execute
  Bind         create bind value method

As a general rule, actions have the same stack effect as their regular Forth
word counterpart, but operand order varies. When there's a "left" operand, it
will generally be the moustache target. The right operand will either be a
number being popped from PS or a literal supplied in the moustache.

It is also important to remember that moustache targets usually have a level of
indirection. For example, the signature of "-{+4}" isn't actually ( n n -- n ),
but rather ( n a -- n ) and is equivalent to "4 + @ swap -" (in efficient HAL).

### Access actions

The @ ! @! actions are straigtforward and pretty much do the same thing as their
regular word counterpart. @{}

"@{}" can't be used with "#". "@!{}" *can* be used with "#" and will have the
effect of pushing a new element to PS. For example, "@!{'foo}" has the signature
( n -- n ) while "@!{'foo #42}" has ( -- n ).

Neither of "@" "!" or "@!" can be used with "!" or "&".

"@A" and "@Ainc" are special and revolve around the A register, which has its
own paragraph below.

### Arithmetics actions

Arithmetic actions all follow the same logic and support all the modifiers.
They're the most "regular" of the actions.

"-^" is the only exception as it reverses operand order. If "-{+4}" is the
equivalent of "4 + @ swap -", "-^{+4}" is the equivalent of "4 + @ -".

### Execute actions

The "execute" action allow indirect calls with offsets. They support only a
select few modifiers. If the target is W, a "drop" will be compiled before the
branch. It is incompatible with "# c w !" modifiers.

### Bind actions

Bind actions have their own paragraphs below.

## Modifiers

Things become interesting when we add modifiers in the mix. Broadly speaking,
they try to expose as much as the HAL machinery as possible, but in terser
semantics.

  Target  R F P A '<val>
  Offset  +<val> -<val>
  Literal #<val>
  Width   c w
  Flags   ! & k
  Recall  ><val>

Modifiers with <val> parameters are parsed with "wordorquote", their whole
content interpreted as Forth code with the expected signature ( -- n ).

Modifier order doesn't matter except for ">", which needs to be the first one
if present.

### Target

Target modifiers change the target of the moustache (which is W by default).

"R" is for "RSP". For example, "@{R+4}" will fetch the second element from the
RS.

"F" means "Frame". This is RSP as it was at the beginning of the word, as
tracked by [rcnt] (see below). For example, "{F-4}" is the equivalent of the
"V1" local variable (see below). "{F-16}" is equivalent to "V4". Those paying
attention will notice that it means that "{F}" refers to the word's return
address regardless of the frame size (unless [rcnt] is messed up).

"P" is for "PSP". For example, "@{P+4}" will fetch the *third* element from the
parameter stack. Why third? Because top of stack doesn't count, it's the W
register. Using the "P" address can be a bit messy because your word might
affect the stack. The address where "P" refer is the one *exactly before* the
action takes place. If there is a need to grow PS, then it will happen before
the action. If there is a need to shrink PS, it happens after the action.

For example, "@{P}" is an inefficient "dup", "@!{P}" is a "swap", "!{P}" is an
inefficient "nip".

"A" means "Address Register" (from the HAL). See paragraph below.

"'" means "Memory address". "<val>" is a hardcoded memory address. It is
important to remember that "<val>" is evaluated at compile time, with its result
being stored as a number in the moustache.

If "<val>" is "@", it's a special value that means "take value from compile-time
PS". This is mostly useful for bind{}.

Examples:

+{R#1}         --> r@ 1+
+{R+4 !#1}     --> r> r> 1+ >r >r
+{!'foo}       --> foo +!
W@A @{+4} @{A} --> @+ swap @ swap
MyStruct :new bind{'@&} MyStruct mybind --> an "anonymous" MyStruct bind

### Offset

Offset, in bytes, is specified by the "+" or "-" modifiers. That number of bytes
will be added to the address before the memory access is made.

The "+" modifier has a special parameter: another "+" (example: "create{++}").
When such a parameter is encountered, we add the offset of the previous
moustache to the current one and on top of that, we include the size of that
moustache. This is mostly useful for defining a series of adjacent fields in a
struct. Example:

  create{}    field1 \ at offset 0
  create{++c} field2 \ offset 4, 8-bit
  create{++c} field3 \ offset 5, 8-bit
  create{++w} field4 \ offset 6, 16-bit
  create{++}  field5 \ offset 8, 32-bit

Sometimes, once you're done describing all your fields, you'd like to store your
struct size somewhere. Here's a little trick you can use:

  0 @{++&} const SZ \ SZ=12

See what we did here? This moustache is an interpreted moustache and the
previous moustache is the "field5" one. It means that previous moustache offset
added to its field size correspond exactly to the struct size, which we "freeze"
in the SZ const.

And later, you'd like to extend that struct with more fields? No problem:
"create{+SZ} field6".

That special target also sets the base Target field of the moustache. This is
needed for "++" to work with the "'" modifier. This allows you to have a
"singleton" set of fields targeting a hardcoded memory address. Example:

  create mymem 42 , 54 ,
  create{'mymem} field1
  create{++}     field2
  @{>field2} . \ prints 54

Notice how the @{} didn't need to be preceded by "mymem". That's because
"field2" directly targets "mymem+4".

Sometimes, fields represent arrays and a series of "++" doesn't quit cut it. We
then need to adjust the offset manually:

  create{}      field1 \ at offset 0
  create{++}    arrayof3ints \ offset 4
  create{>>+12} field3

Why not use "++" for "field3"? Well, you could, but you'd have to take the 4
bytes that were automatically added in your calculations, which would mean
"create{+++8} field3", which is a bit less clearer that "{>>+12}" since it
"8" isn't exactly the size of 3 ints.

### Literal

When this modifier is set, the "n" operand of the action is replaced with a
compile-time literal. For example, "-{+4#42}" is the equivalent of
"4 + @ 42 swap -" (but much more efficient, of course).

### Width

Width modifiers work pretty much exactly like "8b)" and "16b)". If the moustache
has a "c", the access is 8-bit, if it has a "w", it's 16-bit.

### Flags

"!" is the "store" flag. Instead of yielding the result to PS, it will store it
to the same address as specified. For example, "+{!}" is the equivalent of
"+!".

"&" is the "deref" flag. It indicates that instead of working with a source
address, we work on a value directly. For example, "lshift{&#3}" is the
equivalent of "3 lshift". Incompatible with "!".

"k" is the "keep" flag. When set the "argument" of the action (that is, the "not
the target" part of arithmetic actions or the "!" action), which always comes
from PS, is not consumed. For example, "!{k}" is the equivalent of "over swap
!". This only works on arithmetic and "!" actions. Incompatible with "#".

### The ">" modifier

This modifier allows you to load a moustache previously saved with one of the
Bind actions (create{}, value{}, etc.). This effectively allow you to bind
moustaches to names, for example, as field specifications. This modifier copies
the specified moustache as-is, completely overwriting whatever was there. This
means that the ">" modifier should always be the first one of the moustache.
Example:

  create data 42 le, $1234 le,
  create{c+4} some8bfield
  : foo @{>some8bfield} ;
  foo .x \ prints 00000034

There is also a special recall target for the ">" modifier: another ">"
(example: "create{>>}"). It recalls the last moustache as is.

Note that the concept of "previous moustache" is a compile time concept. Also
note that the ">" target is not a regular "<val>" argument and it must not be
followed by a whitespace.

## Whitespaces inside moustaches

As a general rule, whitespaces aren't allowed inside moustaches. However,
"wordorquote" which is used for parsing "<val>" modifiers, needs a whitespace
boundary if it's not quoted.

However, Big Moustache adds a special treatment for the last modifier allowing
it to not end with a whitespace.

This means that if you only have one "<val>" modifier, you can put it last and
thus avoid whitespaces. If you have more than one, the one that isn't the last
needs a whitespace after its "<val>" unless it's a quoted val.

Special targets ">>" "++" and "'@" must not be followed by whitespaces.

Examples:

  @{+foo}
  @{+foo #bar}
  @{+"foo bar"#baz}
  @{++c}
  @{>>+4}

## Working with the A register

Exposing HAL's A register is one of the great aspects making moustaches
powerful. It can decrease PS juggling a lot.

You can set A's value through W@A which copies W to A. This word doesn't drop W
from PS. Then, there's @A{} and @Ainc{} which are described in the paragraph
below.

Once you have an address you can work with in A, then you can play with it with
the full powers of the moustaches. However, one must be aware of A's lifetimes
rules (see [doc/hal]), that is that almost all words will destroy its value!

There is, however, a small list of core words (again, see [doc/hal]) that make
the promise of never touching the A register and those words give you a big
enough sandbox for some really satisfying PS juggling savings.

Moustaches also make the promise of never touching the A register, except of
course for actions/modifiers that explicitly change it.

The S register is extensively used by moustaches and is never preserved. It is
thus not exposed by the moustache API.

### The @A and @Ainc actions

The "@A" action is like a regular "@", but instead of fetching the value to PS
top, it fetches it to HAL's A register. This allows multiple layers of
indirections to be addresses elegantly and efficiently by moustaches.

Let's use an example. Let's say that you have a pointer to a struct in RSP+4 and
you want to increase one of its fields (let's say offset 8) by 1.  You can't
address a field of that structure directly in the moustache. Doing something
like "+{R+4+8 #1}" wouldn't do what you want because it would increase RSP+12,
not what you want at all.

So, do you cede to inefficiency and do something like "@{R+4} +{+8 #1}"? This
results in a push and a drop in PS that are evitable. That makes Virgil a saaad
panda.

What you can do instead is "@A{R+4} +{A+8 #1}". This is the same as the previous
code, but without.

Then, there's "@Ainc", which does the same as "@A", but then increases the
target memory address by the width of the moustache. The "fetch-to-A" operation
is always 32-bit. For example, "@Ainc{c'foo} !{cA}" is the efficient equivalent
to "foo c! 1 foo +!". "@Ainc{w} @{wA}" is the efficient equivalent to
"dup w@ 2 rot +!".

"@A" is incompatible with modifiers "! # c w".
"@Ainc" is incompatible with "! #".

## Binding moustaches to names

"create{...} name" evaluates the specified moustache and then saves it to
memory, bound to "name". Calling "name" yields the address of a moustache
structure (that structure is opaque and only partially exposed by the moustache
API).

That address can be used by the ">" to "recall" that moustache in a particular
action.

### Binding moustaches to behavior

The "bind" action creates a word that, when called, executes the specified
moustache and then calls the specified word with the result of that moustache on
PS top. It is used thus:

  bind{+4} targetword bindingname

The is the functional equivalent to ": bindingname 4 + @ targetword ;". The
binding plays well with immediates, which means something really important: the
target word can be a namespace [doc/lib/ns]! When you target a namespace, which
is an immediate, it will "do its thing" naturally. It means you can do something
like this:

  variable myio'
  bind{'_myio} IO myio
  SomeIO :new myio' !
  : foo 42 myio :seek ;

In that example, my the value of "myio'" changes, "foo" will correctly call
:seek with the new "self" value. It is a frequent pattern in Dusk for singleton
bind{}s to define a variable with the name of the bind with a "'" suffix
(meaning "address of...").

### value{} and value

In the same spirit as bind{}, there is also "value{}" which is behaves like
"bind{} noop" except that it doesn't uselessly compile a call to "noop". In
other words, "value{+4} foo" creates "foo" which is the functional equivalent to
"@{+4}".

But there's more: values can be used as saved moustaches. If, for example, you
want to write to the "foo" value above, you can do "!{>foo #42}" and it's going
to work as if "foo" was a "create{}" instead of a "value{}". This is done by
having a special global flag that indicates whether we're currently recalling a
moustache. The "value{}" bind then checks for that global variable and yields
moustache instead of executing it if we're in a "recall" context.

And on top of that, there's also "value" which is the equivalent of
"here# swap , value{'@}". Full example:

  create data 42 ,
  value{'data} myval
  myval . \ prints 42
  !{>myval #54}
  data @ . \ prints 54
  myval . \ prints 54

  42 value otherval
  otherval . \ prints 42
  !{>otherval #54}
  otherval . \ prints 54

## method{}

method{} is a bound version of execute{}, that is, calling this word is almost
the equivalent of compiling a execute{} with the same moustache. We say "almost"
because unlike a straight execute{}, PS top (the "self" argument) is kept in
place.

A method{} moustache can't be used with "R F A P '" modifiers.

As with value{}s, method{}s can be used as saved moustaches:

  create data 42 , ' abort ,
  : fooimpl ."hello " @ . ;
  method{+4} :foo
  ' fooimpl data !{>:foo}
  data :foo \ prints "hello 42"

## Local variables

It's a common pattern, to avoid PS juggling, to place an element on RS (Return
Stack) and recall that element with r@. It works well, but unfortunately, this
only works with a single element. Another drawback is that this element can be
"buried" by a pattern (a "next" loop for example) that needs to place something
on RS.

A workaround to this is to declare a "private" value near the word and store
temporary values in there. It works too, but because those values are statically
allocated, this can't be done in words that require recursion. Also, it's a bit
verbose.

Local variables are there to the rescue! There are 4 of them: V1 V2 V3 V4. These
words do a simple thing: they reference an element on RS using value{}s. They
are also impervious to being "buried" because they remember their "slot" at
compile time and adjust their compilation accordingly.

In other words, if FRAME is the address in memory of RSP when the word starts
executing and considering the fact that RSP grows "downwards" in memory,
V1=FRAME-4 and V4=FRAME-16.

When using local variables, you are responsible for pushing and popping to/from
RS. Example:

  : foo ( a b c -- ) >r >r >r V1 . spc> V2 . spc> V3 . 2rdrop rdrop ;

  1 2 3 foo \ prints "3 2 1"

  : inc ( a -- a+1 ) >r +{>V1 !#1} V1 rdrop ;
  42 inc . \ prints 43

  \ this works too
  : inc5 ( a -- a+5 ) >r 5 >r begin +{>V1 !#1} next V1 rdrop ;
  42 inc5 . \ prints 47

### Manual [rcnt] adjustments

The "R counter" that determines local variable slots at compile time is
oblivious to conditional code or loops. It's not common to have code that
conditionally maintain separate RS levels (they always need to stay balanced, of
course), but it can happen. For example, in early "exit" paths, we often have to
include a few "rdrop" before the "exit" call. If you have a fancy word that
returns a variable number of arguments, you might end up with >r and r> in
loops. All of this messes up the "R counter". You can manually adjust it through
the [rcnt] variable. For example, if you want your next ">r" to push to V1, you
would precede it with:

  [ 0 [rcnt] ! ]

Another use for manual [rcnt] adjustments is to have local variables to "below"
the word line. For example, if for some reason you'd want "V1" to be bound to
the word's return address, you can assign -4 to [rcnt]:

  : foo [ -4 [rcnt] ! ] $1234 to V1 ; \ returns to address $1234

## Reading moustache documentation

Documentations for units defining publicly accessible moustaches will list them
in a "Fields" section. It will be a list of names with the description of
what the moustache points to. When we refer to a moustache in such
documentation, we will generally mean a "value{}" rather than a "create{}"
because it's offers a more convenient API. If it's not a value{}, it will be
explicitly indicated.

## API

<action>{} *I*
  Execute or compile a moustache.

W@A *I*
  Compile a copy of the W register into the A register.

create{} ( "name" -- )
  Create a new "name" cell, parse enclosed moustache and save it there.

value{} ( "name" -- )
  Like a create{}, but binds a fetch action to the associated name (see
  paragraph above).

bind{} ( "execname" "name" -- )
  Binds the word "execname" to the specified moustache (see paragraph above).

V1 V2 V3 V4
  Built-in value{}s corresponding to F-4 F-8 F-12 F-16.

to ( "valuename" -- ) *I*
  Shortcut for !{}. "to something" is equivalent to "!{>something}".

MOUSTACHESZ ( -- n )
  Size of a moustache struct.

moustache ( -- a )
  Last moustache to have been parsed.

prevmoustache ( -- a )
  Copy of the moustache that was parsed prior to this one.

m< ( -- )
  Parse a moustache from the input stream.

val< ( -- n )
  Parse a "<val>" from the input stream.

moustache) ( -- halop )
  Yield a HAL operand corresponding to the current moustache. This combines the
  "base", "off", "width", "ref" and "applyrcnt" to yield that result.

  For reference, implementation of "@{" is essentially "m< moustache) @,".

moustachewidth) ( halop -- halop )
  Applies current moustache's width to "halop". This is not required if "halop"
  comes from "moustache)", as it's already been applied.

moustacheaddr ( -- a )
  Yields a runtime address corresponding to the current moustache.

?moustache@ ( a -- n )
  Unless the current moustache is a reference, executes @, w@ or c@ depending on
  moustache's width.

moustache! ( n a -- )
  Executes !, w! or c! depending on moustache's width.

?moustachelit ( -- ?n f )
  Yields whether current moustache has a literal and, if it has, yield it as
  "n".
