diff options
author | Zahary Karadjov <zahary@gmail.com> | 2013-05-11 22:47:37 +0300 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2013-05-11 22:47:37 +0300 |
commit | f44a4362bbb74255b8781951c6b1286100176ef3 (patch) | |
tree | 02793b12db243c31e8d0136833cb7621c9f1c0a7 | |
parent | 40b411fb1c319a74daedce524c5d821b6bdc0e45 (diff) | |
download | Nim-f44a4362bbb74255b8781951c6b1286100176ef3.tar.gz |
added a ``noforward`` pragma that enables a new compilation strategy
not requiring forward declarations on a per-module basis
-rw-r--r-- | compiler/ast.nim | 3 | ||||
-rw-r--r-- | compiler/cgen.nim | 4 | ||||
-rw-r--r-- | compiler/passes.nim | 6 | ||||
-rw-r--r-- | compiler/pragmas.nim | 9 | ||||
-rw-r--r-- | compiler/procfind.nim | 3 | ||||
-rw-r--r-- | compiler/semcall.nim | 3 | ||||
-rw-r--r-- | compiler/semstmts.nim | 51 | ||||
-rw-r--r-- | compiler/wordrecg.nim | 4 | ||||
-rw-r--r-- | examples/hallo.nim | 15 |
9 files changed, 76 insertions, 22 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index eb12c977f..3622f0e7a 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -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 diff --git a/compiler/cgen.nim b/compiler/cgen.nim index f034f6675..ddb9ec0ad 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -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: diff --git a/compiler/passes.nim b/compiler/passes.nim index 8d228fe9a..22249edaf 100644 --- a/compiler/passes.nim +++ b/compiler/passes.nim @@ -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 diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index ba761739a..ed3c44e1c 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -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) diff --git a/compiler/procfind.nim b/compiler/procfind.nim index 2db6247e1..cfb9ee2ca 100644 --- a/compiler/procfind.nim +++ b/compiler/procfind.nim @@ -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) diff --git a/compiler/semcall.nim b/compiler/semcall.nim index be41299ad..6c58d609c 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -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) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 2c3adfeda..cf954af92 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -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): diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index 3ad2f45ca..36d08c718 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -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", diff --git a/examples/hallo.nim b/examples/hallo.nim index d94da8c1f..220e9c623 100644 --- a/examples/hallo.nim +++ b/examples/hallo.nim @@ -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) + |