# Macros

Macros conveniently allows the operator to repeat textual input, with or
without placeholders. General Forth mechanisms allow, of course, plenty of ways
to conveniently repeat a piece of logic, but when the repetition is more textual
in nature, there is no obvious way to repeat. Enter macros:

  : greetFoo ." Hello Foo!" ;
  : greetBar ." Hello Bar!" ;
  : greetBaz ." Hello Baz!" ;

This piece of code has no obvious way to avoid the churn of repeating text, but
with macros it becomes:

  thrice" : greet%< .\" Hello %0!\" ;\n" "Foo" "Bar" "Baz"

The command above results in the Dusk interpreter to read the *exact* same text
as previously shown. To achieve this, it uses input overrides (see doc/usage) to
temporarily hijack the input and insert interpolated strings resulting in the
macro format string applied to specified parameters

## Parameters

As shown above, macros will spit quoted contents verbatim until they hit a "%"
character. This character will insert a parameter. If you need a verbatim "%"
character, write "%%".

The inserted parameter can come from two sources:

1. The input stream. If you follow "%" with "<", a quoted string (same rules as
   "stringlist" in lib/str) will be read from the input stream and inserted.
2. A previous parameter. If you follow "%" with a 0-9 digit, a previously read
   parameter will be re-inserted. The digit is the index, in reading order, of
   a parameter previously read. Error occurs if index exceeds read parameters.

The input stream will expect a number of quoted string that exactly corresponds
to the number of "%<" elements in the macro.

## Named macros

The "thrice" word above, a convenience around "times", is for ad-hoc macros.
You can also have named macros:

  macro" greet : greet%< .\" Hello %0!\" ;\n"
  greet "Foo"
  greet "Bar"
  greet "Baz"

The word following macro" will be the macro name, which is a bit counter-
intuitive because it's "inside" the quotes, but well...

Other than that, named macros work like "times" with regards to parameters.

## Compilation and other contexts

Macros override the input stream in a way that makes them very versatile. They
don't merely interpret the macroed code, but inject it in the input stream in a
way that makes it *exactly as if typed*, whatever the context, without yielding
EOF at the end of the override. If you're in the middle of a word compilation
and insert a macro there, the macro will not "run" the words, but compile them
as if they were typed right in there.

If you use a macro in the middle of a CC compilation, then this contents can be
C code, it's going to work.

## API

macro" ( "name macro" -- )
  Create a new macro named "name" with contents "macro". The resulting macro is
  an immediate word.

times" ( n "macro" -- ) *I*
  Executes "macro" n times.

twice" ( "macro" -- ) *I*
  Equivalent to "2 times"".

thrice" ( "macro" -- ) *I*
  Equivalent to "3 times"".
