summary refs log tree commit diff stats
path: root/compiler/semstmts.nim
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2018-04-15 01:07:28 +0200
committerAndreas Rumpf <rumpf_a@web.de>2018-04-15 01:07:28 +0200
commitc08efb4c512fdd094a0386699cbdb8797d841150 (patch)
tree2ab26024c81f252f122fd1149c4032821a394607 /compiler/semstmts.nim
parenta30b52eb6410bff3430c6a1786761a6ded4cd88d (diff)
downloadNim-c08efb4c512fdd094a0386699cbdb8797d841150.tar.gz
implements first version of for-loop macros
Diffstat (limited to 'compiler/semstmts.nim')
-rw-r--r--compiler/semstmts.nim39
1 files changed, 37 insertions, 2 deletions
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 85fe3d793..f90e5c5f9 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -702,11 +702,46 @@ proc isTrivalStmtExpr(n: PNode): bool =
       return false
   result = true
 
+proc handleForLoopMacro(c: PContext; n: PNode): PNode =
+  let iterExpr = n[^2]
+  if iterExpr.kind in nkCallKinds:
+    # we transform
+    # n := for a, b, c in m(x, y, z): Y
+    # to
+    # m(n)
+    let forLoopStmt = magicsys.getCompilerProc("ForLoopStmt")
+    if forLoopStmt == nil: return
+
+    let headSymbol = iterExpr[0]
+    var o: TOverloadIter
+    var match: PSym = nil
+    var symx = initOverloadIter(o, c, headSymbol)
+    while symx != nil:
+      if symx.kind in {skTemplate, skMacro}:
+        if symx.typ.len == 2 and symx.typ[1] == forLoopStmt.typ:
+          if match == nil:
+            match = symx
+          else:
+            localError(n.info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [
+              getProcHeader(match), getProcHeader(symx), $iterExpr])
+      symx = nextOverloadIter(o, c, headSymbol)
+
+    if match == nil: return
+    var callExpr = newNodeI(nkCall, n.info)
+    callExpr.add newSymNode(match)
+    callExpr.add n
+    case match.kind
+    of skMacro: result = semMacroExpr(c, callExpr, callExpr, match, {})
+    of skTemplate: result = semTemplateExpr(c, callExpr, match, {})
+    else: result = nil
+
 proc semFor(c: PContext, n: PNode): PNode =
-  result = n
   checkMinSonsLen(n, 3)
   var length = sonsLen(n)
+  result = handleForLoopMacro(c, n)
+  if result != nil: return result
   openScope(c)
+  result = n
   n.sons[length-2] = semExprNoDeref(c, n.sons[length-2], {efWantIterator})
   var call = n.sons[length-2]
   if call.kind == nkStmtListExpr and isTrivalStmtExpr(call):
@@ -772,7 +807,7 @@ proc typeSectionTypeName(n: PNode): PNode =
   else:
     result = n
   if result.kind != nkSym: illFormedAst(n)
-  
+
 
 proc typeSectionLeftSidePass(c: PContext, n: PNode) =
   # process the symbols on the left side for the whole type section, before