summary refs log tree commit diff stats
path: root/rod/semstmts.nim
diff options
context:
space:
mode:
Diffstat (limited to 'rod/semstmts.nim')
-rwxr-xr-xrod/semstmts.nim171
1 files changed, 107 insertions, 64 deletions
diff --git a/rod/semstmts.nim b/rod/semstmts.nim
index 176fdad1b..b2fae3f31 100755
--- a/rod/semstmts.nim
+++ b/rod/semstmts.nim
@@ -358,49 +358,120 @@ proc semConst(c: PContext, n: PNode): PNode =
     addSon(b, copyTree(def))
     addSon(result, b)
 
+proc transfFieldLoopBody(n: PNode, forLoop: PNode,
+                         tupleType: PType,
+                         tupleIndex, first: int): PNode = 
+  case n.kind
+  of nkEmpty..pred(nkIdent), succ(nkIdent)..nkNilLit: result = n
+  of nkIdent:
+    result = n
+    var L = sonsLen(forLoop)
+    # field name:
+    if first > 0:
+      if n.ident.id == forLoop[0].ident.id:
+        if tupleType.n == nil: 
+          # ugh, there are no field names:
+          result = newStrNode(nkStrLit, "")
+        else:
+          result = newStrNode(nkStrLit, tupleType.n.sons[tupleIndex].sym.name.s)
+        return
+    # other fields:
+    for i in first..L-3:
+      if n.ident.id == forLoop[i].ident.id:
+        var call = forLoop.sons[L-2]
+        var tupl = call.sons[i+1-first]
+        result = newNodeI(nkBracketExpr, n.info)
+        result.add(tupl)
+        result.add(newIntNode(nkIntLit, tupleIndex))
+        break
+  else:
+    result = copyNode(n)
+    newSons(result, sonsLen(n))
+    for i in countup(0, sonsLen(n)-1):
+      result.sons[i] = transfFieldLoopBody(n.sons[i], forLoop,
+                                           tupleType, tupleIndex, first)
+
+proc semForFields(c: PContext, n: PNode, m: TMagic): PNode = 
+  # so that 'break' etc. work as expected, we produce 
+  # a 'while true: stmt; break' loop ...
+  result = newNodeI(nkWhileStmt, n.info)
+  var trueSymbol = StrTableGet(magicsys.systemModule.Tab, getIdent"true")
+  if trueSymbol == nil: GlobalError(n.info, errSystemNeeds, "true")
+
+  result.add(newSymNode(trueSymbol, n.info))
+  var stmts = newNodeI(nkStmtList, n.info)
+  result.add(stmts)
+  
+  var length = sonsLen(n)
+  var call = n.sons[length-2]
+  if length-2 != sonsLen(call)-1 + ord(m==mFieldPairs):
+    GlobalError(n.info, errWrongNumberOfVariables)
+  
+  var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar)
+  if tupleTypeA.kind != tyTuple: InternalError(n.info, "no tuple type!")
+  for i in 1..call.len-1:
+    var tupleTypeB = skipTypes(call.sons[i].typ, abstractVar)
+    if not SameType(tupleTypeA, tupleTypeB):
+      typeMismatch(call.sons[i], tupleTypeA, tupleTypeB)
+  
+  Inc(c.p.nestedLoopCounter)
+  var loopBody = n.sons[length-1]
+  for i in 0..sonsLen(tupleTypeA)-1:
+    openScope(c.tab)
+    var body = transfFieldLoopBody(loopBody, n, tupleTypeA, i,
+                                   ord(m==mFieldPairs))
+    stmts.add(SemStmt(c, body))
+    closeScope(c.tab)
+  Dec(c.p.nestedLoopCounter)
+  var b = newNodeI(nkBreakStmt, n.info)
+  b.add(ast.emptyNode)
+  stmts.add(b)
+  
+proc createCountupNode(c: PContext, rangeNode: PNode): PNode = 
+  # convert ``in 3..5`` to ``in countup(3, 5)``
+  checkSonsLen(rangeNode, 2)
+  result = newNodeI(nkCall, rangeNode.info)
+  var countUp = StrTableGet(magicsys.systemModule.Tab, getIdent"countup")
+  if countUp == nil: GlobalError(rangeNode.info, errSystemNeeds, "countup")
+  newSons(result, 3)
+  result.sons[0] = newSymNode(countup)
+  result.sons[1] = rangeNode.sons[0]
+  result.sons[2] = rangeNode.sons[1]
+
 proc semFor(c: PContext, n: PNode): PNode = 
-  var 
-    v, countup: PSym
-    iter: PType
-    countupNode, call: PNode
   result = n
   checkMinSonsLen(n, 3)
   var length = sonsLen(n)
   openScope(c.tab)
-  if n.sons[length - 2].kind == nkRange: 
-    checkSonsLen(n.sons[length - 2], 2) 
-    # convert ``in 3..5`` to ``in countup(3, 5)``
-    countupNode = newNodeI(nkCall, n.sons[length - 2].info)
-    countUp = StrTableGet(magicsys.systemModule.Tab, getIdent("countup"))
-    if countUp == nil: GlobalError(countupNode.info, errSystemNeeds, "countup")
-    newSons(countupNode, 3)
-    countupnode.sons[0] = newSymNode(countup)
-    countupNode.sons[1] = n.sons[length - 2].sons[0]
-    countupNode.sons[2] = n.sons[length - 2].sons[1]
-    n.sons[length - 2] = countupNode
-  n.sons[length - 2] = semExprWithType(c, n.sons[length - 2], {efWantIterator})
-  call = n.sons[length - 2]
-  if (call.kind != nkCall) or (call.sons[0].kind != nkSym) or
-      (call.sons[0].sym.kind != skIterator): 
+  if n.sons[length-2].kind == nkRange:
+    n.sons[length-2] = createCountupNode(c, n.sons[length-2])
+  n.sons[length-2] = semExprWithType(c, n.sons[length-2], {efWantIterator})
+  var call = n.sons[length-2]
+  if call.kind != nkCall or call.sons[0].kind != nkSym or
+      call.sons[0].sym.kind != skIterator: 
     GlobalError(n.sons[length - 2].info, errIteratorExpected)
-  iter = skipTypes(n.sons[length - 2].typ, {tyGenericInst})
-  if iter.kind != tyTuple: 
-    if length != 3: GlobalError(n.info, errWrongNumberOfVariables)
-    v = newSymS(skForVar, n.sons[0], c)
-    v.typ = iter
-    n.sons[0] = newSymNode(v)
-    addDecl(c, v)
-  else: 
-    if length-2 != sonsLen(iter): GlobalError(n.info, errWrongNumberOfVariables)
-    for i in countup(0, length - 3): 
-      v = newSymS(skForVar, n.sons[i], c)
-      v.typ = iter.sons[i]
-      n.sons[i] = newSymNode(v)
+  elif call.sons[0].sym.magic != mNone:
+    result = semForFields(c, n, call.sons[0].sym.magic)
+  else:
+    var iter = skipTypes(n.sons[length-2].typ, {tyGenericInst})
+    if iter.kind != tyTuple: 
+      if length != 3: GlobalError(n.info, errWrongNumberOfVariables)
+      var v = newSymS(skForVar, n.sons[0], c)
+      v.typ = iter
+      n.sons[0] = newSymNode(v)
       addDecl(c, v)
-  Inc(c.p.nestedLoopCounter)
-  n.sons[length - 1] = SemStmt(c, n.sons[length - 1])
+    else: 
+      if length-2 != sonsLen(iter): 
+        GlobalError(n.info, errWrongNumberOfVariables)
+      for i in countup(0, length - 3): 
+        var v = newSymS(skForVar, n.sons[i], c)
+        v.typ = iter.sons[i]
+        n.sons[i] = newSymNode(v)
+        addDecl(c, v)
+    Inc(c.p.nestedLoopCounter)
+    n.sons[length-1] = SemStmt(c, n.sons[length-1])
+    Dec(c.p.nestedLoopCounter)
   closeScope(c.tab)
-  Dec(c.p.nestedLoopCounter)
 
 proc semRaise(c: PContext, n: PNode): PNode = 
   result = n
@@ -436,34 +507,6 @@ proc semTry(c: PContext, n: PNode): PNode =
     # last child of an nkExcept/nkFinally branch is a statement:
     a.sons[length - 1] = semStmtScope(c, a.sons[length - 1])
 
-proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = 
-  result = copyNode(n)
-  if n.kind != nkGenericParams: InternalError(n.info, "semGenericParamList")
-  for i in countup(0, sonsLen(n)-1): 
-    var a = n.sons[i]
-    if a.kind != nkIdentDefs: illFormedAst(n)
-    var L = sonsLen(a)
-    var def = a.sons[L-1]
-    var typ: PType
-    if a.sons[L-2].kind != nkEmpty: typ = semTypeNode(c, a.sons[L-2], nil)
-    elif def.kind != nkEmpty: typ = newTypeS(tyExpr, c)
-    else: typ = nil
-    for j in countup(0, L-3): 
-      var s: PSym
-      if (typ == nil) or (typ.kind == tyTypeDesc): 
-        s = newSymS(skType, a.sons[j], c)
-        s.typ = newTypeS(tyGenericParam, c)
-      else: 
-        # not a type param, but an expression
-        s = newSymS(skGenericParam, a.sons[j], c)
-        s.typ = typ
-      if def.kind != nkEmpty: s.ast = def
-      s.typ.sym = s
-      if father != nil: addSon(father, s.typ)
-      s.position = i
-      addSon(result, newSymNode(s))
-      addDecl(c, s)
-
 proc addGenericParamListToScope(c: PContext, n: PNode) = 
   if n.kind != nkGenericParams: 
     InternalError(n.info, "addGenericParamListToScope")
@@ -741,7 +784,7 @@ proc semIterator(c: PContext, n: PNode): PNode =
   var t = s.typ
   if t.sons[0] == nil: 
     LocalError(n.info, errXNeedsReturnType, "iterator")
-  if n.sons[codePos].kind == nkEmpty: 
+  if n.sons[codePos].kind == nkEmpty and s.magic == mNone: 
     LocalError(n.info, errImplOfXexpected, s.name.s)
   
 proc semProc(c: PContext, n: PNode): PNode =