bugfix: forwarding of generic procs now works

This commit is contained in:
Araq
2011-07-30 10:42:51 +02:00
parent dce8949b9b
commit 6781da5215
8 changed files with 70 additions and 43 deletions

View File

@@ -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)

View File

@@ -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:

View File

@@ -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()

View File

@@ -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)

View File

@@ -1,5 +1,6 @@
Comex
Eric Doughty-Papassideris
Keita Haga
Philippe Lhoste
Mario Ray Mahardhika
Alex Mitchell

View File

@@ -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

View File

@@ -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

View File

@@ -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