summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-08-02 23:14:38 +0200
committerAraq <rumpf_a@web.de>2012-08-02 23:14:38 +0200
commit7d6500f1de19379cdfc9c6f8a05d43781cf32291 (patch)
tree010e7c625639b3bb3a0f397c19f4d7d06bf76120
parent559980c8901fe56aa8b410c6427fd1467dd69794 (diff)
downloadNim-7d6500f1de19379cdfc9c6f8a05d43781cf32291.tar.gz
idetools improvements; preparation of first class iterators; fixes #183
-rwxr-xr-xcompiler/ast.nim4
-rwxr-xr-xcompiler/ccgstmts.nim21
-rw-r--r--compiler/ccgtrav.nim9
-rwxr-xr-xcompiler/ecmasgen.nim2
-rwxr-xr-xcompiler/importer.nim25
-rw-r--r--compiler/lambdalifting.nim28
-rwxr-xr-xcompiler/msgs.nim2
-rwxr-xr-xcompiler/parser.nim8
-rwxr-xr-xcompiler/semstmts.nim21
-rwxr-xr-xcompiler/semtypes.nim8
-rwxr-xr-xcompiler/sigmatch.nim2
-rwxr-xr-xcompiler/suggest.nim1
12 files changed, 95 insertions, 36 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index ff493e563..071318992 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -200,7 +200,9 @@ type
     nkEnumTy,             # enum body
     nkEnumFieldDef,       # `ident = expr` in an enumeration
     nkReturnToken,        # token used for interpretation
-    nkClosure             # (prc, env)-pair (internally used for code gen)
+    nkClosure,            # (prc, env)-pair (internally used for code gen)
+    nkGotoState,          # used for the state machine (for iterators)
+    nkState               # give a label to a code section (for iterators)
   TNodeKinds* = set[TNodeKind]
 
 type
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 591dd7089..1f480f024 100755
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -92,6 +92,25 @@ template preserveBreakIdx(body: stmt): stmt =
   body
   p.breakIdx = oldBreakIdx
 
+proc genState(p: BProc, n: PNode) =
+  internalAssert n.len == 2 and n.sons[0].kind == nkIntLit
+  let idx = n.sons[0].intVal
+  lineCg(p, cpsStmts, "STATE$1: ;$n", [idx.toRope])
+  genStmts(p, n.sons[1])
+
+proc genGotoState(p: BProc, n: PNode) =
+  # we resist the temptation to translate it into duff's device as it later
+  # will be translated into computed gotos anyway for GCC at least:
+  # switch (x.state) {
+  #   case 0: goto STATE0;
+  # ...
+  var a: TLoc
+  initLocExpr(p, n.sons[0], a)
+  lineF(p, cpsStmts, "switch ($1) {$n", [rdLoc(a)])
+  for i in 0 .. lastOrd(n.sons[0].typ):
+    lineF(p, cpsStmts, "case $1: goto STATE$1;$n", [toRope(i)])
+  lineF(p, cpsStmts, "}$n", [])
+
 proc genSingleVar(p: BProc, a: PNode) =
   var v = a.sons[0].sym
   if sfCompileTime in v.flags: return
@@ -863,5 +882,7 @@ proc genStmts(p: BProc, t: PNode) =
         if prc.getBody.kind != nkEmpty or lfDynamicLib in prc.loc.flags: 
           genProc(p.module, prc)
   of nkParForStmt: genParForStmt(p, t)
+  of nkState: genState(p, t)
+  of nkGotoState: genGotoState(p, t)
   else: internalError(t.info, "genStmts(" & $t.kind & ')')
   
diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim
index 1ff6346f6..5f6f14548 100644
--- a/compiler/ccgtrav.nim
+++ b/compiler/ccgtrav.nim
@@ -44,6 +44,8 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, n: PNode) =
     lineF(p, cpsStmts, "} $n")
   of nkSym:
     let field = n.sym
+    if field.loc.t == nil:
+      internalError(n.info, "genTraverseProc()")
     genTraverseProc(c, ropef("$1.$2", accessor, field.loc.r), field.loc.t)
   else: internalError(n.info, "genTraverseProc()")
 
@@ -73,11 +75,8 @@ proc genTraverseProc(c: var TTraversalClosure, accessor: PRope, typ: PType) =
     if typ.n != nil: genTraverseProc(c, accessor, typ.n)
   of tyTuple:
     let typ = GetUniqueType(typ)
-    if typ.n != nil:
-      genTraverseProc(c, accessor, typ.n)
-    else:
-      for i in countup(0, sonsLen(typ) - 1):
-        genTraverseProc(c, ropef("$1.Field$2", accessor, i.toRope), typ.sons[i])
+    for i in countup(0, sonsLen(typ) - 1):
+      genTraverseProc(c, ropef("$1.Field$2", accessor, i.toRope), typ.sons[i])
   of tyRef, tyString, tySequence:
     lineCg(p, cpsStmts, c.visitorFrmt, accessor)
   of tyProc:
diff --git a/compiler/ecmasgen.nim b/compiler/ecmasgen.nim
index 1ae80c74c..615386a32 100755
--- a/compiler/ecmasgen.nim
+++ b/compiler/ecmasgen.nim
@@ -1468,6 +1468,8 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) =
     if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}: 
       var r2: TCompRes
       genSym(p, n.sons[namePos], r2)
+  of nkGotoState, nkState:
+    internalError(n.info, "first class iterators not implemented")
   else:
     genLineDir(p, n, r)
     gen(p, n, r)
diff --git a/compiler/importer.nim b/compiler/importer.nim
index 19f0574b8..24f7cb5c6 100755
--- a/compiler/importer.nim
+++ b/compiler/importer.nim
@@ -37,7 +37,7 @@ proc checkModuleName*(n: PNode): string =
   var modulename = n.getModuleName
   result = findModule(modulename)
   if result.len == 0:
-    Fatal(n.info, errCannotOpenFile, modulename)
+    LocalError(n.info, errCannotOpenFile, modulename)
 
 proc rawImportSymbol(c: PContext, s: PSym) = 
   # This does not handle stubs, because otherwise loading on demand would be
@@ -109,19 +109,20 @@ proc evalImport(c: PContext, n: PNode): PNode =
   result = n
   for i in countup(0, sonsLen(n) - 1): 
     var f = checkModuleName(n.sons[i])
-    var m = gImportModule(f)
-    if sfDeprecated in m.flags: 
-      Message(n.sons[i].info, warnDeprecated, m.name.s) 
-    # ``addDecl`` needs to be done before ``importAllSymbols``!
-    addDecl(c, m)             # add symbol to symbol table of module
-    importAllSymbols(c, m)
+    if f.len > 0:
+      var m = gImportModule(f)
+      if sfDeprecated in m.flags: 
+        Message(n.sons[i].info, warnDeprecated, m.name.s) 
+      # ``addDecl`` needs to be done before ``importAllSymbols``!
+      addDecl(c, m)             # add symbol to symbol table of module
+      importAllSymbols(c, m)
 
 proc evalFrom(c: PContext, n: PNode): PNode = 
   result = n
   checkMinSonsLen(n, 2)
   var f = checkModuleName(n.sons[0])
-  var m = gImportModule(f)
-  n.sons[0] = newSymNode(m)
-  addDecl(c, m)               # add symbol to symbol table of module
-  for i in countup(1, sonsLen(n) - 1): importSymbol(c, n.sons[i], m)
-  
+  if f.len > 0:
+    var m = gImportModule(f)
+    n.sons[0] = newSymNode(m)
+    addDecl(c, m)               # add symbol to symbol table of module
+    for i in countup(1, sonsLen(n) - 1): importSymbol(c, n.sons[i], m)
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 647daca85..aaba47c70 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -8,7 +8,6 @@
 #
 
 # This include file implements lambda lifting for the transformator.
-# included from transf.nim
 
 import 
   intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os, 
@@ -517,3 +516,30 @@ proc liftLambdas*(n: PNode): PNode =
   var s = n.sons[namePos].sym
   if gCmd == cmdCompileToEcmaScript: return s.getBody
   result = liftLambdas(s, s.getBody)
+
+proc transformIterator*(fn: PSym, body: PNode): PNode =
+  if body.kind == nkEmpty:
+    # ignore forward declaration:
+    result = body
+  # it(a, b) --> (it(a, b), createClosure())
+  # it(a, b) --> ?
+  discard """
+  let c = chain(f, g)
+  
+  for x in c: echo x
+  
+  iterator chain[S, T](a, b: *S->T, args: *S): T =
+    for x in a(args): yield x
+    for x in b(args): yield x
+  
+  # translated to:
+  
+  
+  
+  let c = chain( (f, newClosure(f)), (g, newClosure(g)), newClosure(chain))
+  
+  
+"""
+
+
+
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 714b6f51f..eb427954a 100755
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -344,7 +344,7 @@ const
     warnLanguageXNotSupported: "language \'$1\' not supported [LanguageXNotSupported]", 
     warnCommentXIgnored: "comment \'$1\' ignored [CommentXIgnored]", 
     warnXisPassedToProcVar: "\'$1\' is passed to a procvar; deprecated [XisPassedToProcVar]", 
-    warnAnalysisLoophole: "thread analysis incomplete due to unkown call '$1' [AnalysisLoophole]",
+    warnAnalysisLoophole: "thread analysis incomplete due to unknown call '$1' [AnalysisLoophole]",
     warnDifferentHeaps: "possible inconsistency of thread local heaps [DifferentHeaps]",
     warnWriteToForeignHeap: "write to foreign heap [WriteToForeignHeap]",
     warnImplicitClosure: "implicit closure convention: '$1' [ImplicitClosure]",
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 3d8fc1f7c..f78f07325 100755
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -275,6 +275,7 @@ proc exprList(p: var TParser, endTok: TTokType, result: PNode) =
 
 proc dotExpr(p: var TParser, a: PNode): PNode =
   getTok(p)
+  var info = p.lex.getlineInfo
   optInd(p, a)
   case p.tok.tokType
   of tkType:
@@ -286,7 +287,7 @@ proc dotExpr(p: var TParser, a: PNode): PNode =
     getTok(p)
     addSon(result, a)
   else:
-    result = newNodeI(nkDotExpr, a.info)
+    result = newNodeI(nkDotExpr, info)
     addSon(result, a)
     addSon(result, parseSymbol(p))
 
@@ -758,9 +759,10 @@ proc parseExpr(p: var TParser): PNode =
   case p.tok.tokType:
   of tkIf: result = parseIfExpr(p, nkIfExpr)
   of tkWhen: result = parseIfExpr(p, nkWhenExpr)
-  of tkTry: result = parseTry(p)
-  of tkCase: result = parseCase(p)
   else: result = lowestExpr(p)
+  # XXX needs proper support:
+  #of tkCase: result = parseCase(p)
+  #of tkTry: result = parseTry(p)
 
 proc primary(p: var TParser, skipSuffix = false): PNode = 
   # prefix operator?
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index c82e7d8de..0e882c076 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -835,13 +835,15 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
   closeScope(c.tab)           # close scope for parameters
   popOwner()
   
-proc semIterator(c: PContext, n: PNode): PNode = 
+proc semIterator(c: PContext, n: PNode): PNode =
   result = semProcAux(c, n, skIterator, iteratorPragmas)
   var s = result.sons[namePos].sym
   var t = s.typ
-  if t.sons[0] == nil: 
+  if t.sons[0] == nil:
     LocalError(n.info, errXNeedsReturnType, "iterator")
-  if n.sons[bodyPos].kind == nkEmpty and s.magic == mNone: 
+  # iterators are either 'inline' or 'closure':
+  if s.typ.callConv != ccInline: s.typ.callConv = ccClosure
+  if n.sons[bodyPos].kind == nkEmpty and s.magic == mNone:
     LocalError(n.info, errImplOfXexpected, s.name.s)
   
 proc semProc(c: PContext, n: PNode): PNode = 
@@ -894,12 +896,13 @@ proc evalInclude(c: PContext, n: PNode): PNode =
   addSon(result, n)
   for i in countup(0, sonsLen(n) - 1): 
     var f = checkModuleName(n.sons[i])
-    var fileIndex = f.fileInfoIdx
-    if ContainsOrIncl(c.includedFiles, fileIndex): 
-      LocalError(n.info, errRecursiveDependencyX, f.extractFilename)
-    else:
-      addSon(result, semStmt(c, gIncludeFile(f)))
-      Excl(c.includedFiles, fileIndex)
+    if f.len > 0:
+      var fileIndex = f.fileInfoIdx
+      if ContainsOrIncl(c.includedFiles, fileIndex): 
+        LocalError(n.info, errRecursiveDependencyX, f.extractFilename)
+      else:
+        addSon(result, semStmt(c, gIncludeFile(f)))
+        Excl(c.includedFiles, fileIndex)
   
 proc setLine(n: PNode, info: TLineInfo) =
   for i in 0 .. <safeLen(n): setLine(n.sons[i], info)
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index a0e2283a3..8e3a4dda4 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -870,9 +870,13 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   of nkType: result = n.typ
   of nkStmtListType: result = semStmtListType(c, n, prev)
   of nkBlockType: result = semBlockType(c, n, prev)
-  else: 
+  else:
     LocalError(n.info, errTypeExpected)
-    result = errorType(c)
+    if prev != nil and prev.kind == tyForward:
+      prev.kind = tyProxy
+      result = prev
+    else:
+      result = errorType(c)
   
 proc setMagicType(m: PSym, kind: TTypeKind, size: int) = 
   m.typ.kind = kind
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index ba0cba749..9273d5add 100755
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -70,7 +70,7 @@ proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode,
   c.calleeSym = callee
   c.calleeScope = calleeScope
   initIdTable(c.bindings)
-  if binding != nil:
+  if binding != nil and callee.kind in RoutineKinds:
     var typeParams = callee.ast[genericParamsPos]
     for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1):
       var formalTypeParam = typeParams.sons[i-1].typ
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index 240316cec..10d50a6b7 100755
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -214,7 +214,6 @@ proc suggestExpr*(c: PContext, node: PNode) =
     var n = findClosestDot(node)
     if n == nil: n = node
     else: cp = cpExact
-    
     if n.kind == nkDotExpr and cp == cpExact:
       var obj = safeSemExpr(c, n.sons[0])
       suggestFieldAccess(c, obj, outputs)