documented the `noforward` pragma

This commit is contained in:
Zahary Karadjov 2013-05-12 16:14:28 +03:00
commit 1d29d24465
4 changed files with 60 additions and 2 deletions

View file

@ -914,12 +914,13 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if sfNoForward in c.module.flags and if sfNoForward in c.module.flags and
sfSystemModule notin c.module.flags: sfSystemModule notin c.module.flags:
addInterfaceOverloadableSymAt(c, c.currentScope, s) addInterfaceOverloadableSymAt(c, c.currentScope, s)
s.flags.incl sfForward
return return
else: else:
s = n[namePos].sym s = n[namePos].sym
typeIsDetermined = s.typ == nil typeIsDetermined = s.typ == nil
if typeIsDetermined: assert phase == stepCompileBody # if typeIsDetermined: assert phase == stepCompileBody
else: assert phase == stepDetermineType # else: assert phase == stepDetermineType
# before compiling the proc body, set as current the scope # before compiling the proc body, set as current the scope
# where the proc was declared # where the proc was declared
let oldScope = c.currentScope let oldScope = c.currentScope

View file

@ -4648,6 +4648,51 @@ Example:
.. code-block:: nimrod .. code-block:: nimrod
{.deadCodeElim: on.} {.deadCodeElim: on.}
NoForward pragma
----------------
The `noforward`:idx pragma can be used to turn on and off a special compilation
mode that to large extent eliminates the need for forward declarations. In this
mode, the proc definitions may appear out of order and the compiler will postpone
their semantic analysis and compilation until it actually needs to generate code
using the definitions. In this regard, this mode is similar to the modus operandi
of dynamic scripting languages, where the function calls are not resolved until
the code is executed. Here is the detailed algorithm taken by the compiler:
1. When a callable symbol is first encountered, the compiler will only note the
symbol callable name and it will add it to the appropriate overload set in the
current scope. At this step, it won't try to resolve any of the type expressions
used in the signature of the symbol (so they can refer to other not yet defined
symbols).
2. When a top level call is encountered (usually at the very end of the module),
the compiler will try to determine the actual types of all of the symbols in the
matching overload set. This is a potentially recursive process as the signatures
of the symbols may include other call expressions, whoose types will be resolved
at this point too.
3. Finally, after the best overload is picked, the compiler will start compiling
the body of the respective symbol. This in turn will lead the compiler to discover
more call expresions that need to be resolved and steps 2 and 3 will be repeated
as necessary.
Please note that if a callable symbol is never used in this scenario, its body
will never be compiled. This is the default behavior leading to best compilation
times, but if exhaustive compilation of all definitions is required, using
``nimrod check`` provides this option as well.
Example:
.. code-block: nimrod
{. noforward: on .}
proc foo(x: int) =
bar x
proc bar(x: int) =
echo x
foo(10)
Pragma pragma Pragma pragma
------------- -------------

View file

@ -0,0 +1,10 @@
{. noforward: on .}
proc foo(x: int) =
bar x
proc bar(x: int) =
echo x
foo(10)

View file

@ -56,6 +56,8 @@ Compiler Additions
to be turned on explicitly via ``--warning[ShadowIdent]:on``. to be turned on explicitly via ``--warning[ShadowIdent]:on``.
- The compiler now supports almost every pragma in a ``push`` pragma. - The compiler now supports almost every pragma in a ``push`` pragma.
- Generic converters have been implemented. - Generic converters have been implemented.
- Added a ``noforward`` pragma enabling a special compilation mode that largely
eliminates the need for forward declarations.
Language Additions Language Additions