macros for proc types, macros for types (#13778)

* new minor feature: macros for proc types, to be documented

* Finished the implementation and added tests

* [skip ci] Describe the new custom pragmas in the manual and the changelog

Co-authored-by: Zahary Karadjov <zahary@gmail.com>
This commit is contained in:
Andreas Rumpf 2020-03-31 21:14:05 +02:00 • committed by GitHub
commit 9134bb9cfb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 303 additions and 140 deletions

View file

@ -5353,26 +5353,6 @@ powerful programming construct that still suffices. So the "check list" is:
(4) Else: Use a macro.
Macros as pragmas
-----------------
Whole routines (procs, iterators etc.) can also be passed to a template or
a macro via the pragma notation:
.. code-block:: nim
template m(s: untyped) = discard
proc p() {.m.} = discard
This is a simple syntactic transformation into:
.. code-block:: nim
template m(s: untyped) = discard
m:
proc p() = discard
For Loop Macro
--------------
@ -6408,29 +6388,6 @@ the created global variables within a module is not defined, but all of them
will be initialized after any top-level variables in their originating module
and before any variable in a module that imports it.
pragma pragma
-------------
The ``pragma`` pragma can be used to declare user defined pragmas. This is
useful because Nim's templates and macros do not affect pragmas. User
defined pragmas are in a different module-wide scope than all other symbols.
They cannot be imported from a module.
Example:
.. code-block:: nim
when appType == "lib":
{.pragma: rtl, exportc, dynlib, cdecl.}
else:
{.pragma: rtl, importc, dynlib: "client.dll", cdecl.}
proc p*(a, b: int): int {.rtl.} =
result = a+b
In the example a new pragma named ``rtl`` is introduced that either imports
a symbol from a dynamic library or exports the symbol for dynamic library
generation.
Disabling certain messages
--------------------------
Nim generates some warnings and hints ("line too long") that may annoy the
@ -7127,6 +7084,34 @@ used. To see if a value was provided, `defined(FooBar)` can be used.
The syntax `-d:flag` is actually just a shortcut for `-d:flag=true`.
User-defined pragmas
====================
pragma pragma
-------------
The ``pragma`` pragma can be used to declare user defined pragmas. This is
useful because Nim's templates and macros do not affect pragmas. User
defined pragmas are in a different module-wide scope than all other symbols.
They cannot be imported from a module.
Example:
.. code-block:: nim
when appType == "lib":
{.pragma: rtl, exportc, dynlib, cdecl.}
else:
{.pragma: rtl, importc, dynlib: "client.dll", cdecl.}
proc p*(a, b: int): int {.rtl.} =
result = a+b
In the example a new pragma named ``rtl`` is introduced that either imports
a symbol from a dynamic library or exports the symbol for dynamic library
generation.
Custom annotations
------------------
It is possible to define custom typed pragmas. Custom pragmas do not effect
@ -7193,6 +7178,51 @@ More examples with custom pragmas:
alpha {.editRange: [0.0..1.0], animatable.}: float32
Macro pragmas
-------------
All macros and templates can also be used as pragmas. They can be attached
to routines (procs, iterators, etc), type names or type expressions. The
compiler will perform the following simple syntactic transformations:
.. code-block:: nim
template command(name: string, def: untyped) = discard
proc p() {.command("print").} = discard
This is translated to:
.. code-block:: nim
command("print"):
proc p() = discard
------
.. code-block:: nim
type
AsyncEventHandler = proc (x: Event) {.async.}
This is translated to:
.. code-block:: nim
type
AsyncEventHandler = async(proc (x: Event))
------
.. code-block:: nim
type
MyObject {.schema: "schema.protobuf".} = object
This is translated to a call to the ``schema`` macro with a `nnkTypeDef`
AST node capturing both the left-hand side and right-hand side of the
definition. The macro can return a potentially modified `nnkTypeDef` tree
will replace the original row in the type section.
When multiple macro pragmas are applied to the same definition, the
compiler will apply them consequently from left to right. Each macro
will receive as input the output of the previous one.
Foreign function interface
@ -7269,7 +7299,6 @@ In the example the external name of ``p`` is set to ``prefixp``. Only ``$1``
is available and a literal dollar sign must be written as ``$$``.
Bycopy pragma
-------------
@ -7313,6 +7342,7 @@ checked.
**Future directions**: GC'ed memory should be allowed in unions and the GC
should scan unions conservatively.
Packed pragma
-------------
The ``packed`` pragma can be applied to any ``object`` type. It ensures