Ducktype Macros

Shaun McCance <shaunm at gnome.org>
Mon Jun 20 12:17:46 EDT 2016

I'd like to add a simple macro system to Ducktype, reusing the syntax
we use for defining entity substitutions. Defining a macro would look
just like an entity definition, except with a () after the name. You'd
then refer to arguments numerically. So, for example, say you link to
functions frequently in API docs. You could define this:

  @define func() $code[.function >$1;]()

(Or more verbosely:)

  @define func() $code[style=function xref=$1;]()

Then you could use it like this:

  To frobnicate a file, use $func(g_frobnicate).

You could have multiple arguments as well:

  @define func() $code[.function >$1;]($2;)
  To frobnicate a file, use $func(frobnicate)(g_frobnicate).

The single-argument form looks just like an inline element. I don't
think that's a problem for two reasons: 1) Defined macros would just
always take precedence, so don't define macros with element names you
want to use. 2) If you do have a name conflict, you can force it to
parse as an element with an empty attribute list.

  @define gui() $gui[style=button]($1;)
  A button: $gui(My Button). Not a button: $gui[](My Label).

The syntax for referring to arguments also looks just like the syntax
for referring to characters numerically. For example, outside a macro
definition, "$21;" means "!" (U+0021). How big of a problem this is
(and how we deal with it) depends on what we do with references beyond
the number of arguments passed:

1) If you pass two arguments and reference $3;, you get the empty
string. This is probably what people expect, honestly. But it means
that every decimal-looking number can't be used for a character. One
possible solution is that we limit macros to up to nine arguments, so
only $1; thru $9; are blank by default. I think it's unlikely U+0001
thru U+0009 are a big loss.

2) If you pass two arguments and reference $3;, you get U+0003. This is
probably not what people expect, but it avoids issues with $21;, unless
you actually pass 21 arguments.

3) We make macros declare exactly how many arguments they take, like
one of these:

  @define func()() $code[.function >$1;]($2;)
  @define func(2)
$code[.function >$1;]($2;)

4) We reference arguments differently, maybe like this:

  @define func() $code[.function >${1}](${2})


Also, would it be useful to be able to specify defaults? If (3) above,
maybe a syntax like this:

  @define func()(function) $code[style=$2; xref=$1;]()

If (4) above, maybe a syntax like this:

  @define func() $code[style=${2:function} xref=${1}]

--
Shaun