Hello everyone!
I am developing some DSLs using nim's macro system, and I would like to implement my own function syntax. My aim is to have the syntax to look quite similarly to Python's def (https://docs.python.org/3/library/typing.html). However, I can't seem to get the function signature to even enter the macro's parsing. Consider this:
macro my_func(func_signature : untyped, func_body : untyped) =
echo "Macro logic here..."
my_func something(a : float = 0.5) -> float:
return a + 0.5
This would return this error:
Error: expected: ')', but got: '='
While, on the other hand, by simply removing the : in a : float = 0.5, or by using any other symbol in its place (like $), the code would correctly enter the macro block:
macro my_func(func_signature : untyped, func_body : untyped) =
echo "Macro logic here..."
my_func something(a float = 0.5) -> float:
return a + 0.5
my_func something(a $ float = 0.5) -> float:
return a + 0.5
Is there something I'm missing here? Why isn't the a : float = 0.5 construct supported? Shouldn't it be the same as how proc's function signature is working?
What do you mean?
I wouldn't want the users of my DSL to interface with the proc construct directly, but to deal with my_func (or def, or whatever name I come up with), as many things are abstracted in the macro to make the DSL work.
By the way, the DSL is for DSP and audio synthesis, it's still quite in its early stages, but you can find it here: https://github.com/vitreo12/omni
You can get a peek at the current syntax from the examples folder ( https://github.com/vitreo12/omni/tree/master/omni/examples ). There, in the AnalogDelay.omni example, you can see that what I'm currently using for custom functions is called def, but it only works with this syntax:
def something(a float = 0.5):
return a + 0.5
I see your point, but I find proc foo(args: ...): ... {.customMacro.} to be not so user friendly compared to simply def foo(args: ...):.
Especially considering that I am building this DSL also for teaching/learning purpose of DSP/audio algorithms, so I can expect people using it not to have much if any code experiences, especially in nim.
If you insist (and I agree with Araq you probably shouldn't ... ), you should probably be aware of https://nim-lang.org/docs/filters.html which would allow you to do such a translation in a standard, compose-able manner -- which may boil down to just replacing "def" with "proc".
I am not sure if it will work for your specific use case, but some macros/pragmas could be set for a context (once in the file, or a block, essentially - see e.g. https://nim-lang.org/docs/manual.html#pragmas-push-and-pop-pragmas) , and there are other ways to apply a macro to a block of definitions rather than to a specific one through the {.pragma.} syntax - e.g.
dspcode: > proc foo(args:) ... > ....
Where dspcode is a macro that does the magic onto it's subtree. What's left is just the proc<->def exchange.