# 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/io]) 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 string is taken from the
   input stream through "wordorquote" (see [doc/usage/io]) 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 word-or-quotes that exactly corresponds
to the number of "%<" elements in the macro.

You can also use "%-" which consumes an argument from the input stream, places
it in the appropriate 0-9 slot, but doesn't spit it in the macro's result right
away. You can use this to "drop" an argument, or simply use it in an order that
is different from the input argument order.

## 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

## 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"".
