summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--doc/lib.txt3
-rw-r--r--lib/pure/future.nim111
-rw-r--r--tests/closure/tclosuremacro.nim43
-rw-r--r--web/nimrod.ini2
4 files changed, 158 insertions, 1 deletions
diff --git a/doc/lib.txt b/doc/lib.txt
index a209357f7..3ca519c9e 100644
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -373,6 +373,9 @@ Miscellaneous
 * `logging <logging.html>`_
   This module implements a simple logger.
 
+* `future <future.html>`_
+  This module implements new experimental features. Currently the syntax
+  sugar for anonymous procedures.
 
 Database support
 ----------------
diff --git a/lib/pure/future.nim b/lib/pure/future.nim
new file mode 100644
index 000000000..1eb95df2c
--- /dev/null
+++ b/lib/pure/future.nim
@@ -0,0 +1,111 @@
+#
+#
+#            Nimrod's Runtime Library
+#        (c) Copyright 2014 Dominik Picheta
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements experimental features which may soon be moved to
+## the system module (or other more appropriate modules).
+
+import macros
+
+proc createProcType(p, b: PNimrodNode): PNimrodNode {.compileTime.} =
+  #echo treeRepr(p)
+  #echo treeRepr(b)
+  result = newNimNode(nnkProcTy)
+  var formalParams = newNimNode(nnkFormalParams)
+
+  expectKind(b, nnkIdent)
+  formalParams.add b
+
+  case p.kind
+  of nnkPar:
+    for i in 0 .. <p.len:
+      let ident = p[i]
+      var identDefs = newNimNode(nnkIdentDefs)
+      identDefs.add newIdentNode("i" & $i)
+      identDefs.add(ident)
+      identDefs.add newEmptyNode()
+      formalParams.add identDefs
+  of nnkIdent:
+    var identDefs = newNimNode(nnkIdentDefs)
+    identDefs.add newIdentNode("i0")
+    identDefs.add(p)
+    identDefs.add newEmptyNode()
+    formalParams.add identDefs
+  else:
+    error("Incorrect type list in proc type declaration.")
+  
+  result.add formalParams
+  result.add newEmptyNode()
+  #echo(treeRepr(result))
+  #echo(result.toStrLit())
+
+macro `=>`*(p, b: expr): expr {.immediate.} =
+  ## Syntax sugar for anonymous procedures.
+  ##
+  ## ..code-block:: nimrod
+  ##
+  ##   proc passTwoAndTwo(f: (int, int) -> int): int =
+  ##     f(2, 2)
+  ##
+  ##   passTwoAndTwo((x, y) => x + y) # 4
+  
+  echo treeRepr(p)
+  #echo(treeRepr(b))
+  var params: seq[PNimrodNode] = @[newIdentNode("auto")]
+
+  case p.kind
+  of nnkPar:
+    for c in children(p):
+      var identDefs = newNimNode(nnkIdentDefs)
+      case c.kind
+      of nnkExprColonExpr:
+        identDefs.add(c[0])
+        identDefs.add(c[1])
+        identDefs.add(newEmptyNode())
+      of nnkIdent:
+        identDefs.add(c)
+        identDefs.add(newEmptyNode())
+        identDefs.add(newEmptyNode())
+      else:
+        error("Incorrect procedure parameter list.")
+      params.add(identDefs)
+  of nnkIdent:
+    var identDefs = newNimNode(nnkIdentDefs)
+    identDefs.add(p)
+    identDefs.add(newEmptyNode())
+    identDefs.add(newEmptyNode())
+    params.add(identDefs)
+  of nnkInfix:
+    if p[0].kind == nnkIdent and p[0].ident == !"->":
+      var procTy = createProcType(p[1], p[2])
+      params[0] = procTy[0][0]
+      for i in 1 .. <procTy[0].len:
+        params.add(procTy[0][i])
+    else:
+      error("Expected proc type (->) got (" & $p[0].ident & ").")
+  else:
+    error("Incorrect procedure parameter list.")
+  result = newProc(params = params, body = b, procType = nnkLambda)
+  #echo(result.treeRepr)
+  echo(result.toStrLit())
+  #return result # TODO: Bug?
+
+macro `->`*(p, b: expr): expr {.immediate.} =
+  ## Syntax sugar for procedure types.
+  ##
+  ## ..code-block:: nimrod
+  ##
+  ##   proc pass2(f: (float, float) -> float): float =
+  ##     f(2, 2)
+  ##   
+  ##   # is the same as:
+  ##
+  ##   proc pass2(f: proc (x, y: float): float): float =
+  ##     f(2, 2)
+
+  createProcType(p, b)
diff --git a/tests/closure/tclosuremacro.nim b/tests/closure/tclosuremacro.nim
new file mode 100644
index 000000000..80d89a090
--- /dev/null
+++ b/tests/closure/tclosuremacro.nim
@@ -0,0 +1,43 @@
+discard """
+  output: '''10
+10
+10
+3
+3
+noReturn
+'''
+"""
+
+import future
+
+when false:
+  proc twoParams(x: (int, int) -> int): int =
+    result = x(5, 5)
+
+  proc oneParam(x: int -> int): int =
+    x(5)
+
+  proc noParams(x: () -> int): int =
+    result = x()
+
+  proc noReturn(x: () -> void) =
+    x()
+
+  proc doWithOneAndTwo(f: (int, int) -> int): int =
+    f(1,2)
+
+  echo twoParams(proc (a, b): auto = a + b)
+  echo twoParams((x, y) => x + y)
+
+  echo oneParam(x => x+5) 
+
+  echo noParams(() => 3)
+
+  echo doWithOneAndTwo((x, y) => x + y)
+
+  noReturn(() -> void => echo("noReturn"))
+
+proc pass2(f: (int, int) -> int): (int) -> int =
+  (x: int) -> int => f(2, x)
+
+#echo pass2((x, y) => x + y)
diff --git a/web/nimrod.ini b/web/nimrod.ini
index b29bcff30..14701ecea 100644
--- a/web/nimrod.ini
+++ b/web/nimrod.ini
@@ -63,7 +63,7 @@ srcdoc2: "pure/asyncio;pure/actors;core/locks;pure/oids;pure/endians;pure/uri"
 srcdoc2: "pure/nimprof;pure/unittest;packages/docutils/highlite"
 srcdoc2: "packages/docutils/rst;packages/docutils/rstast"
 srcdoc2: "packages/docutils/rstgen;pure/logging;pure/asyncdispatch;pure/asyncnet"
-srcdoc2: "pure/rawsockets;pure/asynchttpserver;pure/net;pure/selectors"
+srcdoc2: "pure/rawsockets;pure/asynchttpserver;pure/net;pure/selectors;pure/future"
 
 webdoc: "wrappers/libcurl;pure/md5;wrappers/mysql;wrappers/iup"
 webdoc: "wrappers/sqlite3;wrappers/postgres;wrappers/tinyc"