summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-07-30 10:42:51 +0200
committerAraq <rumpf_a@web.de>2011-07-30 10:42:51 +0200
commit6781da5215df16602a266c33c0834eae47ede04b (patch)
treeda6a155b7dab420c5feaa7e45b42bba8ab7689cf
parentdce8949b9b05af3bac9d5ec0866b99ef22f78384 (diff)
downloadNim-6781da5215df16602a266c33c0834eae47ede04b.tar.gz
bugfix: forwarding of generic procs now works
-rwxr-xr-xcompiler/cgen.nim37
-rwxr-xr-xcompiler/lookups.nim2
-rwxr-xr-xcompiler/seminst.nim43
-rwxr-xr-xcompiler/semstmts.nim15
-rwxr-xr-xcontributors.txt1
-rw-r--r--tests/accept/compile/tforwardgeneric.nim11
-rwxr-xr-xtodo.txt2
-rwxr-xr-xweb/news.txt2
8 files changed, 70 insertions, 43 deletions
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index b89d2d7fc..431aade09 100755
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -585,19 +585,15 @@ proc initFrame(p: BProc, procname, filename: PRope): PRope =
 proc deinitFrame(p: BProc): PRope =
   result = ropecg(p.module, "#popFrame();$n")
 
-proc genProcAux(m: BModule, prc: PSym) = 
-  var 
-    p: BProc
-    generatedProc, header, returnStmt, procname, filename: PRope
-    res, param: PSym
-  p = newProc(prc, m)
-  header = genProcHeader(m, prc)
-  if (gCmd != cmdCompileToLLVM) and (lfExportLib in prc.loc.flags): 
+proc genProcAux(m: BModule, prc: PSym) =
+  var p = newProc(prc, m)
+  var header = genProcHeader(m, prc)
+  if gCmd != cmdCompileToLLVM and lfExportLib in prc.loc.flags: 
     header = con("N_LIB_EXPORT ", header)
-  returnStmt = nil
+  var returnStmt: PRope = nil
   assert(prc.ast != nil)
   if sfPure notin prc.flags and prc.typ.sons[0] != nil:
-    res = prc.ast.sons[resultPos].sym # get result symbol
+    var res = prc.ast.sons[resultPos].sym # get result symbol
     if not isInvalidReturnType(prc.typ.sons[0]): 
       # declare the result symbol:
       assignLocalVar(p, res)
@@ -611,9 +607,10 @@ proc genProcAux(m: BModule, prc: PSym) =
         incl(res.loc.flags, lfIndirect)
         res.loc.s = OnUnknown
   for i in countup(1, sonsLen(prc.typ.n) - 1): 
-    param = prc.typ.n.sons[i].sym
+    var param = prc.typ.n.sons[i].sym
     assignParam(p, param)
   genStmts(p, prc.ast.sons[codePos]) # modifies p.locals, p.init, etc.
+  var generatedProc: PRope
   if sfPure in prc.flags: 
     generatedProc = ropeff("$1 {$n$2$3$4}$n", "define $1 {$n$2$3$4}$n",
         [header, p.s[cpsLocals], p.s[cpsInit], p.s[cpsStmts]])
@@ -622,8 +619,8 @@ proc genProcAux(m: BModule, prc: PSym) =
     if optStackTrace in prc.options: 
       getFrameDecl(p)
       app(generatedProc, p.s[cpsLocals])
-      procname = CStringLit(p, generatedProc, prc.name.s)
-      filename = CStringLit(p, generatedProc, toFilename(prc.info))
+      var procname = CStringLit(p, generatedProc, prc.name.s)
+      var filename = CStringLit(p, generatedProc, toFilename(prc.info))
       app(generatedProc, initFrame(p, procname, filename))
     else: 
       app(generatedProc, p.s[cpsLocals])
@@ -821,15 +818,14 @@ proc registerModuleToMain(m: PSym) =
     appff(mainModInit, "$1();$n", "call void ()* $1$n", [initname])
   
 proc genInitCode(m: BModule) = 
-  var initname, prc, procname, filename: PRope
   if optProfiler in m.initProc.options: 
     # This does not really belong here, but there is no good place for this
     # code. I don't want to put this to the proc generation as the
     # ``IncludeStr`` call is quite slow.
     discard lists.IncludeStr(m.headerFiles, "<cycle.h>")
-  initname = getInitName(m.module)
-  prc = ropeff("N_NOINLINE(void, $1)(void) {$n", 
-               "define void $1() noinline {$n", [initname])
+  var initname = getInitName(m.module)
+  var prc = ropeff("N_NOINLINE(void, $1)(void) {$n", 
+                   "define void $1() noinline {$n", [initname])
   if m.typeNodes > 0: 
     appcg(m, m.s[cfsTypeInit1], "static #TNimNode $1[$2];$n", 
           [m.typeNodesName, toRope(m.typeNodes)])
@@ -843,8 +839,8 @@ proc genInitCode(m: BModule) =
   if optStackTrace in m.initProc.options and not m.PreventStackTrace: 
     app(prc, m.initProc.s[cpsLocals])
     app(prc, m.s[cfsTypeInit1])
-    procname = CStringLit(m.initProc, prc, m.module.name.s)
-    filename = CStringLit(m.initProc, prc, toFilename(m.module.info))
+    var procname = CStringLit(m.initProc, prc, m.module.name.s)
+    var filename = CStringLit(m.initProc, prc, toFilename(m.module.info))
     app(prc, initFrame(m.initProc, procname, filename))
   else:
     app(prc, m.initProc.s[cpsLocals])
@@ -940,7 +936,8 @@ proc finishModule(m: BModule) =
     # Note: ``genProc`` may add to ``m.forwardedProcs``, so we cannot use
     # a ``for`` loop here
     var prc = m.forwardedProcs[i]
-    if sfForward in prc.flags: InternalError(prc.info, "still forwarded")
+    if sfForward in prc.flags: 
+      InternalError(prc.info, "still forwarded: " & prc.name.s)
     genProcNoForward(m, prc)
     inc(i)
   assert(gForwardedProcsCounter >= i)
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index a2cb434a0..324618447 100755
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -49,7 +49,7 @@ proc getSymRepr*(s: PSym): string =
   
 proc CloseScope*(tab: var TSymTab) = 
   # check if all symbols have been used and defined:
-  if (tab.tos > len(tab.stack)): InternalError("CloseScope")
+  if tab.tos > len(tab.stack): InternalError("CloseScope")
   var it: TTabIter
   var s = InitTabIter(it, tab.stack[tab.tos-1])
   while s != nil:
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index a73a0d9bf..87f988ed9 100755
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -65,6 +65,35 @@ proc removeDefaultParamValues(n: PNode) =
         # not possible... XXX We don't solve this issue here.
         a.sons[L-1] = ast.emptyNode
 
+proc instantiateBody(c: PContext, n: PNode, result: PSym) =
+  if n.sons[codePos].kind != nkEmpty:
+    # add it here, so that recursive generic procs are possible:
+    addDecl(c, result)
+    pushProcCon(c, result)
+    if result.kind in {skProc, skMethod, skConverter}: 
+      addResult(c, result.typ.sons[0], n.info)
+      addResultNode(c, n)
+    n.sons[codePos] = semStmtScope(c, n.sons[codePos])
+    if result.kind == skIterator:
+      # XXX Bad hack for tests/titer2:
+      n.sons[codePos] = transform(c.module, n.sons[codePos])
+    #echo "code instantiated ", result.name.s
+    excl(result.flags, sfForward)
+    popProcCon(c)
+
+proc fixupInstantiatedSymbols(c: PContext, s: PSym) =
+  for i in countup(0, Len(generics) - 1):
+    if generics[i].genericSym.id == s.id:
+      var oldPrc = generics[i].instSym
+      pushInfoContext(oldPrc.info)
+      openScope(c.tab)
+      var n = oldPrc.ast
+      n.sons[codePos] = copyTree(s.ast.sons[codePos])
+      if n.sons[paramsPos].kind != nkEmpty: addParams(c, oldPrc.typ.n)
+      instantiateBody(c, n, oldPrc)
+      closeScope(c.tab)
+      popInfoContext()
+
 proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, 
                       info: TLineInfo): PSym = 
   # generates an instantiated proc
@@ -103,20 +132,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
   ParamsTypeCheck(c, result.typ)
   var oldPrc = GenericCacheGet(c, entry)
   if oldPrc == nil:
-    # add it here, so that recursive generic procs are possible:
     generics.add(entry)
-    addDecl(c, result)
-    if n.sons[codePos].kind != nkEmpty: 
-      pushProcCon(c, result)
-      if result.kind in {skProc, skMethod, skConverter}: 
-        addResult(c, result.typ.sons[0], n.info)
-        addResultNode(c, n)
-      n.sons[codePos] = semStmtScope(c, n.sons[codePos])
-      if fn.kind == skIterator:
-        # XXX Bad hack for tests/titer2:
-        n.sons[codePos] = transform(c.module, n.sons[codePos])
-      popProcCon(c)
-      #echo "code instantiated ", result.name.s
+    instantiateBody(c, n, result)
   else:
     result = oldPrc
   popInfoContext()
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 3444ccfca..553989c40 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -397,7 +397,7 @@ proc semRaise(c: PContext, n: PNode): PNode =
   if n.sons[0].kind != nkEmpty: 
     n.sons[0] = semExprWithType(c, n.sons[0])
     var typ = n.sons[0].typ
-    if (typ.kind != tyRef) or (typ.sons[0].kind != tyObject): 
+    if typ.kind != tyRef or typ.sons[0].kind != tyObject: 
       localError(n.info, errExprCannotBeRaised)
   
 proc semTry(c: PContext, n: PNode): PNode = 
@@ -593,9 +593,6 @@ proc semLambda(c: PContext, n: PNode): PNode =
   
 proc semProcAux(c: PContext, n: PNode, kind: TSymKind, 
                 validPragmas: TSpecialWords): PNode = 
-  var 
-    proto: PSym
-    gp: PNode
   result = n
   checkSonsLen(n, codePos + 1)
   var s = semIdentDef(c, n.sons[0], kind)
@@ -604,6 +601,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
   s.ast = n
   pushOwner(s)
   openScope(c.tab)
+  var gp: PNode
   if n.sons[genericParamsPos].kind != nkEmpty: 
     n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos])
     gp = n.sons[genericParamsPos]
@@ -622,8 +620,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
   else: 
     s.typ = newTypeS(tyProc, c)
     addSon(s.typ, nil)
-  proto = SearchForProc(c, s, c.tab.tos - 2) # -2 because we have a scope open
-                                             # for parameters
+  var proto = SearchForProc(c, s, c.tab.tos-2) # -2 because we have a scope
+                                               # open for parameters
   if proto == nil: 
     if c.p.owner.kind != skModule: 
       s.typ.callConv = ccClosure
@@ -666,7 +664,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     if n.sons[genericParamsPos].kind == nkEmpty: 
       ParamsTypeCheck(c, s.typ)
       pushProcCon(c, s)
-      if (s.typ.sons[0] != nil) and (kind != skIterator): 
+      if s.typ.sons[0] != nil and kind != skIterator: 
         addResult(c, s.typ.sons[0], n.info)
       if sfImportc notin s.flags: 
         # no semantic checking for importc:
@@ -677,6 +675,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
       if s.typ.sons[0] != nil and kind != skIterator: 
         addDecl(c, newSym(skUnknown, getIdent("result"), nil))
       n.sons[codePos] = semGenericStmtScope(c, n.sons[codePos], {})
+      fixupInstantiatedSymbols(c, s)
     if sfImportc in s.flags: 
       # so we just ignore the body after semantic checking for importc:
       n.sons[codePos] = ast.emptyNode
@@ -744,7 +743,7 @@ proc semMacroDef(c: PContext, n: PNode): PNode =
   
 proc evalInclude(c: PContext, n: PNode): PNode = 
   result = newNodeI(nkStmtList, n.info)
-  addSon(result, n)           # the rodwriter needs include information!
+  addSon(result, n)
   for i in countup(0, sonsLen(n) - 1): 
     var f = getModuleFile(n.sons[i])
     var fileIndex = includeFilename(f)
diff --git a/contributors.txt b/contributors.txt
index 4d0e2bb51..37978dc3f 100755
--- a/contributors.txt
+++ b/contributors.txt
@@ -1,5 +1,6 @@
 Comex
 Eric Doughty-Papassideris
+Keita Haga
 Philippe Lhoste
 Mario Ray Mahardhika
 Alex Mitchell
diff --git a/tests/accept/compile/tforwardgeneric.nim b/tests/accept/compile/tforwardgeneric.nim
new file mode 100644
index 000000000..84bef15cc
--- /dev/null
+++ b/tests/accept/compile/tforwardgeneric.nim
@@ -0,0 +1,11 @@
+discard """
+  output: "1.0000000000000000e+00 10"
+"""
+
+proc p[T](a, b: T): T
+
+echo p(0.9, 0.1), " ", p(9, 1)
+
+proc p[T](a, b: T): T =
+  result  = a + b
+
diff --git a/todo.txt b/todo.txt
index 69b0b40e2..217a79551 100755
--- a/todo.txt
+++ b/todo.txt
@@ -18,7 +18,6 @@ version 0.9.0
 =============
 
 - add --deadlock_prevention:on|off switch? timeout for locks?
-- bug: forward proc for generic seems broken
 - warning for implicit openArray -> varargs convention
 - implement explicit varargs
 - tests: run modules that contain "#RUN_ME", compile the other
@@ -31,6 +30,7 @@ Bugs
 - bug: generic assign still buggy
   - Optimization: If we use a temporary for the result anyway the code gen
     should make use of this fact to generate better code...
+  - bug: memset() without type field initialization?
   - special case the generic assign that needs to care about case objects
 
 
diff --git a/web/news.txt b/web/news.txt
index cb1da8773..5058d1355 100755
--- a/web/news.txt
+++ b/web/news.txt
@@ -15,6 +15,8 @@ Bugfixes
 - Fixed a serious bug concerning different instantiations of a generic proc.
 - Fixed a newly introduced bug where a wrong ``EIO`` exception was raised for
   the end of file for text files that do not end with a newline.
+- Bugfix c2nim, c2pas: the ``--out`` option has never worked properly.
+- Bugfix: forwarding of generic procs never worked.
 
 
 Changes affecting backwards compatibility