added a `noforward` pragma that enables a new compilation strategy
not requiring forward declarations on a per-module basis
This commit is contained in:
parent
40b411fb1c
commit
f44a4362bb
9 changed files with 76 additions and 22 deletions
|
|
@ -284,6 +284,9 @@ const
|
|||
|
||||
sfHoist* = sfVolatile ## proc return value can be hoisted
|
||||
|
||||
sfNoForward* = sfRegister
|
||||
# forward declarations are not required (per module)
|
||||
|
||||
const
|
||||
# getting ready for the future expr/stmt merge
|
||||
nkWhen* = nkWhenStmt
|
||||
|
|
|
|||
|
|
@ -842,8 +842,10 @@ proc requestConstImpl(p: BProc, sym: PSym) =
|
|||
if sfExportc in sym.flags and generatedHeader != nil:
|
||||
app(generatedHeader.s[cfsData], headerDecl)
|
||||
|
||||
proc isActivated(prc: PSym): bool = prc.typ != nil
|
||||
|
||||
proc genProc(m: BModule, prc: PSym) =
|
||||
if sfBorrow in prc.flags: return
|
||||
if sfBorrow in prc.flags or not isActivated(prc): return
|
||||
fillProcLoc(prc)
|
||||
if {sfForward, sfFromGeneric} * prc.flags != {}: addForwardedProc(m, prc)
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ proc processModule(module: PSym, stream: PLLStream, rd: PRodReader) =
|
|||
s = stream
|
||||
while true:
|
||||
openParsers(p, fileIdx, s)
|
||||
var code = p.parseAll
|
||||
|
||||
if sfSystemModule notin module.flags:
|
||||
# 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 implicitIncludes, nkIncludeStmt, a
|
||||
|
||||
while true:
|
||||
var n = parseTopLevelStmt(p)
|
||||
if n.kind == nkEmpty: break
|
||||
if not processTopLevelStmt(n, a): break
|
||||
processTopLevelStmt(code, a)
|
||||
|
||||
closeParsers(p)
|
||||
if s.kind != llsStdIn: break
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ const
|
|||
wFatal, wDefine, wUndef, wCompile, wLink, wLinkSys, wPure, wPush, wPop,
|
||||
wBreakpoint, wWatchpoint, wPassL, wPassC, wDeadCodeElim, wDeprecated,
|
||||
wFloatChecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
|
||||
wLinearScanEnd, wPatterns, wEffects}
|
||||
wLinearScanEnd, wPatterns, wEffects, wNoForward}
|
||||
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
wNosideEffect, wSideEffect, wNoreturn, wDynLib, wHeader,
|
||||
wDeprecated, wExtern, wThread, wImportcpp, wImportobjc, wNoStackFrame,
|
||||
|
|
@ -182,7 +182,11 @@ proc onOff(c: PContext, n: PNode, op: TOptions) =
|
|||
proc pragmaDeadCodeElim(c: PContext, n: PNode) =
|
||||
if IsTurnedOn(c, n): incl(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) =
|
||||
if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
|
||||
var sw = whichKeyword(n.sons[1].ident)
|
||||
|
|
@ -552,6 +556,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
|||
noVal(it)
|
||||
incl(sym.flags, sfThread)
|
||||
of wDeadCodeElim: pragmaDeadCodeElim(c, it)
|
||||
of wNoForward: pragmaNoForward(c, it)
|
||||
of wMagic: processMagic(c, it, sym)
|
||||
of wCompileTime:
|
||||
noVal(it)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ proc equalGenericParams(procA, procB: PNode): bool =
|
|||
result = true
|
||||
|
||||
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.
|
||||
var it: TIdentIter
|
||||
result = initIdentIter(it, c.tab.stack[tos], fn.Name)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ proc sameMethodDispatcher(a, b: PSym): bool =
|
|||
# be disambiguated by the programmer; this way the right generic is
|
||||
# instantiated.
|
||||
|
||||
proc determineType(c: PContext, s: PSym)
|
||||
|
||||
proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||
filter: TSymKinds): TCandidate =
|
||||
var initialBinding: PNode
|
||||
|
|
@ -58,6 +60,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
|||
|
||||
while sym != nil:
|
||||
if sym.kind in filter:
|
||||
determineType(c, sym)
|
||||
initCandidate(z, sym, initialBinding, o.lastOverloadScope)
|
||||
z.calleeSym = sym
|
||||
matches(c, n, orig, z)
|
||||
|
|
|
|||
|
|
@ -884,15 +884,37 @@ proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
|
|||
addResult(c, s.typ.sons[0], n.info, s.kind)
|
||||
addResultNode(c, n)
|
||||
|
||||
proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
validPragmas: TSpecialWords): PNode =
|
||||
type
|
||||
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)
|
||||
if result != nil: return result
|
||||
result = n
|
||||
checkSonsLen(n, bodyPos + 1)
|
||||
var s = semIdentDef(c, n.sons[0], kind)
|
||||
n.sons[namePos] = newSymNode(s)
|
||||
s.ast = n
|
||||
var s: PSym
|
||||
var usesAutoForwarding = false
|
||||
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)
|
||||
openScope(c.tab)
|
||||
var gp: PNode
|
||||
|
|
@ -924,10 +946,12 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
|||
# add it here, so that recursive procs are possible:
|
||||
# -2 because we have a scope open for parameters
|
||||
if sfGenSym in s.flags: nil
|
||||
elif kind in OverloadableSyms:
|
||||
addInterfaceOverloadableSymAt(c, s, c.tab.tos - 2)
|
||||
else:
|
||||
addInterfaceDeclAt(c, s, c.tab.tos - 2)
|
||||
elif kind in OverloadableSyms:
|
||||
if not usesAutoForwarding:
|
||||
addInterfaceOverloadableSymAt(c, s, c.tab.tos - 2)
|
||||
else:
|
||||
if not usesAutoForwarding:
|
||||
addInterfaceDeclAt(c, s, c.tab.tos - 2)
|
||||
if n.sons[pragmasPos].kind != nkEmpty:
|
||||
pragma(c, s, n.sons[pragmasPos], validPragmas)
|
||||
else:
|
||||
|
|
@ -992,7 +1016,12 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
|||
popOwner()
|
||||
if n.sons[patternPos].kind != nkEmpty:
|
||||
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 =
|
||||
result = semProcAux(c, n, skIterator, iteratorPragmas)
|
||||
var s = result.sons[namePos].sym
|
||||
|
|
@ -1055,7 +1084,7 @@ proc semMacroDef(c: PContext, n: PNode): PNode =
|
|||
if n.sons[bodyPos].kind == nkEmpty:
|
||||
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)
|
||||
addSon(result, n)
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ type
|
|||
wFloatchecks, wNanChecks, wInfChecks,
|
||||
wAssertions, wPatterns, wWarnings,
|
||||
wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags,
|
||||
wDeadCodeElim, wSafecode,
|
||||
wDeadCodeElim, wSafecode, wNoForward,
|
||||
wPragma,
|
||||
wCompileTime, wNoInit,
|
||||
wPassc, wPassl, wBorrow, wDiscardable,
|
||||
|
|
@ -135,7 +135,7 @@ const
|
|||
|
||||
"assertions", "patterns", "warnings", "hints",
|
||||
"optimization", "raises", "writes", "reads", "size", "effects", "tags",
|
||||
"deadcodeelim", "safecode",
|
||||
"deadcodeelim", "safecode", "noforward",
|
||||
"pragma",
|
||||
"compiletime", "noinit",
|
||||
"passc", "passl", "borrow", "discardable", "fieldchecks",
|
||||
|
|
|
|||
|
|
@ -1,3 +1,16 @@
|
|||
# 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)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue