diff options
-rwxr-xr-x | compiler/cgen.nim | 37 | ||||
-rwxr-xr-x | compiler/lookups.nim | 2 | ||||
-rwxr-xr-x | compiler/seminst.nim | 43 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 15 | ||||
-rwxr-xr-x | contributors.txt | 1 | ||||
-rw-r--r-- | tests/accept/compile/tforwardgeneric.nim | 11 | ||||
-rwxr-xr-x | todo.txt | 2 | ||||
-rwxr-xr-x | web/news.txt | 2 |
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 |