added a `noforward` pragma that enables a new compilation strategy

not requiring forward declarations on a per-module basis
This commit is contained in:
Zahary Karadjov 2013-05-11 22:47:37 +03:00
commit f44a4362bb
9 changed files with 76 additions and 22 deletions

View file

@ -284,6 +284,9 @@ const
sfHoist* = sfVolatile ## proc return value can be hoisted sfHoist* = sfVolatile ## proc return value can be hoisted
sfNoForward* = sfRegister
# forward declarations are not required (per module)
const const
# getting ready for the future expr/stmt merge # getting ready for the future expr/stmt merge
nkWhen* = nkWhenStmt nkWhen* = nkWhenStmt

View file

@ -842,8 +842,10 @@ proc requestConstImpl(p: BProc, sym: PSym) =
if sfExportc in sym.flags and generatedHeader != nil: if sfExportc in sym.flags and generatedHeader != nil:
app(generatedHeader.s[cfsData], headerDecl) app(generatedHeader.s[cfsData], headerDecl)
proc isActivated(prc: PSym): bool = prc.typ != nil
proc genProc(m: BModule, prc: PSym) = proc genProc(m: BModule, prc: PSym) =
if sfBorrow in prc.flags: return if sfBorrow in prc.flags or not isActivated(prc): return
fillProcLoc(prc) fillProcLoc(prc)
if {sfForward, sfFromGeneric} * prc.flags != {}: addForwardedProc(m, prc) if {sfForward, sfFromGeneric} * prc.flags != {}: addForwardedProc(m, prc)
else: else:

View file

@ -177,6 +177,7 @@ proc processModule(module: PSym, stream: PLLStream, rd: PRodReader) =
s = stream s = stream
while true: while true:
openParsers(p, fileIdx, s) openParsers(p, fileIdx, s)
var code = p.parseAll
if sfSystemModule notin module.flags: if sfSystemModule notin module.flags:
# XXX what about caching? no processing then? what if I change the # XXX what about caching? no processing then? what if I change the
@ -186,10 +187,7 @@ proc processModule(module: PSym, stream: PLLStream, rd: PRodReader) =
processImplicits implicitImports, nkImportStmt, a processImplicits implicitImports, nkImportStmt, a
processImplicits implicitIncludes, nkIncludeStmt, a processImplicits implicitIncludes, nkIncludeStmt, a
while true: processTopLevelStmt(code, a)
var n = parseTopLevelStmt(p)
if n.kind == nkEmpty: break
if not processTopLevelStmt(n, a): break
closeParsers(p) closeParsers(p)
if s.kind != llsStdIn: break if s.kind != llsStdIn: break

View file

@ -42,7 +42,7 @@ const
wFatal, wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop, wFatal, wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop,
wBreakpoint, wWatchpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated, wBreakpoint, wWatchpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated,
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
wLinearScanEnd, wPatterns, wEffects} wLinearScanEnd, wPatterns, wEffects, wNoForward}
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader, wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
wDeprecated, wExtern, wThread, wImportcpp, wImportobjc, wNoStackFrame, wDeprecated, wExtern, wThread, wImportcpp, wImportobjc, wNoStackFrame,
@ -182,7 +182,11 @@ proc onOff(c: PContext, n: PNode, op: TOptions) =
proc pragmaDeadCodeElim(c: PContext, n: PNode) = proc pragmaDeadCodeElim(c: PContext, n: PNode) =
if IsTurnedOn(c, n): incl(c.module.flags, sfDeadCodeElim) if IsTurnedOn(c, n): incl(c.module.flags, sfDeadCodeElim)
else: excl(c.module.flags, sfDeadCodeElim) else: excl(c.module.flags, sfDeadCodeElim)
proc pragmaNoForward(c: PContext, n: PNode) =
if IsTurnedOn(c, n): incl(c.module.flags, sfNoForward)
else: excl(c.module.flags, sfNoForward)
proc processCallConv(c: PContext, n: PNode) = proc processCallConv(c: PContext, n: PNode) =
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
var sw = whichKeyword(n.sons[1].ident) var sw = whichKeyword(n.sons[1].ident)
@ -552,6 +556,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
noVal(it) noVal(it)
incl(sym.flags, sfThread) incl(sym.flags, sfThread)
of wDeadCodeElim: pragmaDeadCodeElim(c, it) of wDeadCodeElim: pragmaDeadCodeElim(c, it)
of wNoForward: pragmaNoForward(c, it)
of wMagic: processMagic(c, it, sym) of wMagic: processMagic(c, it, sym)
of wCompileTime: of wCompileTime:
noVal(it) noVal(it)

View file

@ -31,7 +31,8 @@ proc equalGenericParams(procA, procB: PNode): bool =
result = true result = true
proc SearchForProc*(c: PContext, fn: PSym, tos: int): PSym = proc SearchForProc*(c: PContext, fn: PSym, tos: int): PSym =
# Searchs for the fn in the symbol table. If the parameter lists are exactly # Searchs for a forward declaration or a "twin" symbol of fn
# in the symbol table. If the parameter lists are exactly
# the same the sym in the symbol table is returned, else nil. # the same the sym in the symbol table is returned, else nil.
var it: TIdentIter var it: TIdentIter
result = initIdentIter(it, c.tab.stack[tos], fn.Name) result = initIdentIter(it, c.tab.stack[tos], fn.Name)

View file

@ -32,6 +32,8 @@ proc sameMethodDispatcher(a, b: PSym): bool =
# be disambiguated by the programmer; this way the right generic is # be disambiguated by the programmer; this way the right generic is
# instantiated. # instantiated.
proc determineType(c: PContext, s: PSym)
proc resolveOverloads(c: PContext, n, orig: PNode, proc resolveOverloads(c: PContext, n, orig: PNode,
filter: TSymKinds): TCandidate = filter: TSymKinds): TCandidate =
var initialBinding: PNode var initialBinding: PNode
@ -58,6 +60,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
while sym != nil: while sym != nil:
if sym.kind in filter: if sym.kind in filter:
determineType(c, sym)
initCandidate(z, sym, initialBinding, o.lastOverloadScope) initCandidate(z, sym, initialBinding, o.lastOverloadScope)
z.calleeSym = sym z.calleeSym = sym
matches(c, n, orig, z) matches(c, n, orig, z)

View file

@ -884,15 +884,37 @@ proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
addResult(c, s.typ.sons[0], n.info, s.kind) addResult(c, s.typ.sons[0], n.info, s.kind)
addResultNode(c, n) addResultNode(c, n)
proc semProcAux(c: PContext, n: PNode, kind: TSymKind, type
validPragmas: TSpecialWords): PNode = TProcActivationSteps = enum
stepRegisterSymbol,
stepDetermineType,
stepActivate
proc isForwardDecl(s: PSym): bool =
InternalAssert s.kind == skProc
result = s.ast[bodyPos].kind != nkEmpty
proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
validPragmas: TSpecialWords,
phase = stepRegisterSymbol): PNode =
result = semProcAnnotation(c, n) result = semProcAnnotation(c, n)
if result != nil: return result if result != nil: return result
result = n result = n
checkSonsLen(n, bodyPos + 1) checkSonsLen(n, bodyPos + 1)
var s = semIdentDef(c, n.sons[0], kind) var s: PSym
n.sons[namePos] = newSymNode(s) var usesAutoForwarding = false
s.ast = n if n[namePos].kind != nkSym:
s = semIdentDef(c, n.sons[0], kind)
n.sons[namePos] = newSymNode(s)
s.ast = n
if sfNoForward in c.module.flags and
sfSystemModule notin c.module.flags:
addInterfaceOverloadableSymAt(c, s, c.tab.tos - 1)
return
else:
s = n[namePos].sym
usesAutoForwarding = s.typ == nil
pushOwner(s) pushOwner(s)
openScope(c.tab) openScope(c.tab)
var gp: PNode var gp: PNode
@ -924,10 +946,12 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
# add it here, so that recursive procs are possible: # add it here, so that recursive procs are possible:
# -2 because we have a scope open for parameters # -2 because we have a scope open for parameters
if sfGenSym in s.flags: nil if sfGenSym in s.flags: nil
elif kind in OverloadableSyms: elif kind in OverloadableSyms:
addInterfaceOverloadableSymAt(c, s, c.tab.tos - 2) if not usesAutoForwarding:
else: addInterfaceOverloadableSymAt(c, s, c.tab.tos - 2)
addInterfaceDeclAt(c, s, c.tab.tos - 2) else:
if not usesAutoForwarding:
addInterfaceDeclAt(c, s, c.tab.tos - 2)
if n.sons[pragmasPos].kind != nkEmpty: if n.sons[pragmasPos].kind != nkEmpty:
pragma(c, s, n.sons[pragmasPos], validPragmas) pragma(c, s, n.sons[pragmasPos], validPragmas)
else: else:
@ -992,7 +1016,12 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
popOwner() popOwner()
if n.sons[patternPos].kind != nkEmpty: if n.sons[patternPos].kind != nkEmpty:
c.patterns.add(s) c.patterns.add(s)
proc determineType(c: PContext, s: PSym) =
if s.typ != nil: return
#if s.magic != mNone: return
discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType)
proc semIterator(c: PContext, n: PNode): PNode = proc semIterator(c: PContext, n: PNode): PNode =
result = semProcAux(c, n, skIterator, iteratorPragmas) result = semProcAux(c, n, skIterator, iteratorPragmas)
var s = result.sons[namePos].sym var s = result.sons[namePos].sym
@ -1055,7 +1084,7 @@ proc semMacroDef(c: PContext, n: PNode): PNode =
if n.sons[bodyPos].kind == nkEmpty: if n.sons[bodyPos].kind == nkEmpty:
LocalError(n.info, errImplOfXexpected, s.name.s) LocalError(n.info, errImplOfXexpected, s.name.s)
proc evalInclude(c: PContext, n: PNode): PNode = proc evalInclude(c: PContext, n: PNode): PNode =
result = newNodeI(nkStmtList, n.info) result = newNodeI(nkStmtList, n.info)
addSon(result, n) addSon(result, n)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):

View file

@ -53,7 +53,7 @@ type
wFloatchecks, wNanChecks, wInfChecks, wFloatchecks, wNanChecks, wInfChecks,
wAssertions, wPatterns, wWarnings, wAssertions, wPatterns, wWarnings,
wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags, wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags,
wDeadCodeElim, wSafecode, wDeadCodeElim, wSafecode, wNoForward,
wPragma, wPragma,
wCompileTime, wNoInit, wCompileTime, wNoInit,
wPassc, wPassl, wBorrow, wDiscardable, wPassc, wPassl, wBorrow, wDiscardable,
@ -135,7 +135,7 @@ const
"assertions", "patterns", "warnings", "hints", "assertions", "patterns", "warnings", "hints",
"optimization", "raises", "writes", "reads", "size", "effects", "tags", "optimization", "raises", "writes", "reads", "size", "effects", "tags",
"deadcodeelim", "safecode", "deadcodeelim", "safecode", "noforward",
"pragma", "pragma",
"compiletime", "noinit", "compiletime", "noinit",
"passc", "passl", "borrow", "discardable", "fieldchecks", "passc", "passl", "borrow", "discardable", "fieldchecks",

View file

@ -1,3 +1,16 @@
# Hello world program # Hello world program
echo "Hello World" import macros, strutils
{. noforward: on .}
proc hola(x: int) =
echo "HOLA"
comuEsta(x)
proc comuEsta(x: int) =
echo "COMU ESTA"
echo x
hola(10)