How to nest macro definitions in M4? - macros

I would like to define a macro that can define more macros as:
define(`master_macro',
`foreachq(`slave_macro', `$*',
define(`slave_macro', ...)'
then I can use master_macro to define more similar slave_macros as:
master_macro(m1, m2, m3, ...)
The reason why I need this is that the number and names of slave_macro are unknown when I write M4 macros.

What you are asking for can certainly be done. Here's an example:
$ cat file
changequote(`[',`]')dnl
define([factory],[dnl
define($1,banana)dnl
define($2,split)dnl
])dnl
factory(hello,world)dnl
hello world
$ m4 file
banana split
I think the problem is your usage of the undefined macro foreachq.

Related

What is the point of quoting the argument of the macro?

Reading the docs of the m4 macro language I have found that example:
changequote([,])dnl
define([gl_STRING_MODULE_INDICATOR],
[dnl comment
GNULIB_[]translit([[$1]], [a-z], [A-Z])=1dnl
])dnl
gl_STRING_MODULE_INDICATOR([strcase])
which produces:
GNULIB_STRCASE=1
But if one omits to quote strcase we have the same result:
gl_STRING_MODULE_INDICATOR(strcase)
produces
GNULIB_STRCASE=1
Why quoting strcase?
The quotes are required in case strcase is defined as a macro. For example, if we have define(strcase, foo), then gl_STRING_MODULE_INDICATOR(strcase) will expand first into gl_STRING_MODULE_INDICATOR(foo) and then into GNULIB_FOO=1.
In general, well-written m4 input will continue to function when certain words unexpectedly happen to be defined as macros.

How to escape the . when using dot notation commandline arguments

I want to pass in a config like:
foo
blah.bar: blah.bar
another.thing: some.thing
And I want to do this on the commmandline, osmething like:
python my_script.py foo.blah.bar=blah.bar foo.another.thing=some.thing
Obviously, this would give me instead:
foo
blah
bar: blah.bar
another
thing: some.thing
... which is not what I want. How can I escape any periods (.) when using dot notation with omegaconf.OmegaConf.from_cli() ?
Based on the comment here, I think you could do something like:
python my_script.py foo[blah.bar]=blah.bar foo[another.thing]=some.thing
But I've never used omegaconf, so please don't beat me up for guessing :)
This is not supported.
You can file a feature request but it's not going to be high pri. I suggest that you use a different separator in your keys.

Elixir macros, quoting bitstring patternmatch types

I am working on a project in which I am likely to be writing a lot of code of the form:
defmodule Kind
defstruct [name1, name2, name3]
#type t :: %Kind{name1: integer(), name2: integer(), name3: binary()}
def unpack(input) do
with <<name1::integer-8>> <- Enum.take(input, 1),
<<name2::integer-little-32>> <- Enum.take(input, 4),
<<name3::binary-10>> <- Enum.take(input, 10),
do: %Kind{name1: name1, name2: name2, name3: name3>>
end
end
(for arbitrary sets of input names and types, input being a binary stream producing one byte at a time)
It would be very useful to be able to handle this in a macro, so that I could simply write (for example) use Unpack quote([{name1, integer-8}, {name2, integer-little-32}, {name3, binary-10}]) and automatically generate the necessary struct, typedef, and unpacking function, for arbitrary named fields of fixed sizes. Could even expand it, add a third field in the tuples to pass a function to handle variably-sized types. Unfortunately, when I try to do a simpler version of that (only taking one sized field, and only matching 1 to it):
defmodule Unpack do
defmacro testmacro({name, kind}) do
quote do
<<unquote(name)::unqote(kind)>> = 1
end
end
end
The system tells me it's got invalid arguments for quote/1. I assume this is because the "types" used in bitstring pattern-matching are a special form, as are bitstring literals in general, and those particular items are not used anywhere else.
So, how do I get around that? I've got more than a dozen kinds of packed struct to unpack, each with between five and twenty different fields. If I don't do this I'll probably resort to Vim macros to at least save my hands... but that won't really help with having large amounts of extremely repetitive code to maintain.
Two things: you have a typo in unquote and the RHS must be a binary so that the pattern matches. With those changes, your code works for me:
defmodule Unpack do
defmacro unpack({name, kind}) do
quote do
<<unquote(name)::unquote(kind)>> = "a"
end
end
end
defmodule Main do
import Unpack
def main do
unpack({foo, integer-8})
IO.inspect foo
end
end
Main.main
Output:
97

How to refer to last argument in m4 macro

How does one refer to the last argument in a given list of arguments in an m4 macro? I have a requirement to pull the last argument and generate macro expansion based on that.
This is not particularly elegant, but it works:
define(`last',`ifelse(`$#',`0',`',`$#',`1',`$1',`last(shift($#))')')dnl
last(foo,bar,baz)
# more elegant solution:
changequote([,])
define([LEN], [$#])
define([LAST], [pushdef([$0], $LEN($#))$0($#)[]popdef([$0])])
define([LAST_BUT_ONE], [pushdef([$0], $decr(LEN($#)))$0($#)[]popdef([$0])])
LAST(foo, bar, baz)
LAST_BUT_ONE(foo, bar, baz)

Extract to an OCaml file by using "Recursive Extraction" in Coq

I want to extract a function foo in Coq to an OCaml file. Because my real function have to use the Recursive Extraction, when I run a program it output the extracted OCaml code on the cmd. But I would like to output it to a file, for example: foo.ml
Recursive Extraction foo.
When I tried:
Recursive Extraction "foo.ml" foo.
or Recursive Extraction foo "foo.ml"
I got an error: Syntax error: "." expected after [vernac:command] (in [vernac_aux]).
My question is: Am I able to extract the function foo to a file by using the Recursive Extraction syntax? Thank you for your help.
According to the manual (http://coq.inria.fr/distrib/V8.4/refman/Reference-Manual027.html), Extraction "foo.ml" foo will extract foo and recursively all its dependencies into foo.ml, i.e. you don't need Recursive in that case, it is only used for extraction on stdout.