summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semstmts.nim5
-rw-r--r--doc/manual.txt45
-rw-r--r--tests/compile/tnoforward.nim10
-rw-r--r--web/news.txt2
4 files changed, 60 insertions, 2 deletions
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 3acd00065..efe5c9217 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -914,12 +914,13 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     if sfNoForward in c.module.flags and
        sfSystemModule notin c.module.flags:
       addInterfaceOverloadableSymAt(c, c.currentScope, s)
+      s.flags.incl sfForward
       return
   else:
     s = n[namePos].sym
     typeIsDetermined = s.typ == nil
-    if typeIsDetermined: assert phase == stepCompileBody
-    else: assert phase == stepDetermineType
+    # if typeIsDetermined: assert phase == stepCompileBody
+    # else: assert phase == stepDetermineType
   # before compiling the proc body, set as current the scope
   # where the proc was declared
   let oldScope = c.currentScope
diff --git a/doc/manual.txt b/doc/manual.txt
index 22aa22266..bc9b81bad 100644
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -4648,6 +4648,51 @@ Example:
 .. code-block:: nimrod
   {.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
 -------------
diff --git a/tests/compile/tnoforward.nim b/tests/compile/tnoforward.nim
new file mode 100644
index 000000000..0359ff348
--- /dev/null
+++ b/tests/compile/tnoforward.nim
@@ -0,0 +1,10 @@
+{. noforward: on .}
+
+proc foo(x: int) =
+  bar x
+
+proc bar(x: int) =
+  echo x
+
+foo(10)
+
diff --git a/web/news.txt b/web/news.txt
index ef4255402..7c46e550a 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -56,6 +56,8 @@ Compiler Additions
   to be turned on explicitly via ``--warning[ShadowIdent]:on``.
 - The compiler now supports almost every pragma in a ``push`` pragma.
 - Generic converters have been implemented.
+- Added a ``noforward`` pragma enabling a special compilation mode that largely
+  eliminates the need for forward declarations.
 
 
 Language Additions