diff options
author | Araq <rumpf_a@web.de> | 2012-11-20 23:58:45 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-11-20 23:58:45 +0100 |
commit | 022ff2e86e12b1920a73b67878cd9ee05293d15d (patch) | |
tree | 22445e62747e1f10a5112ea43071ccef0e01af94 /compiler | |
parent | 1dfc57c5fffc425ffe9c79551463de8a386f8697 (diff) | |
download | Nim-022ff2e86e12b1920a73b67878cd9ee05293d15d.tar.gz |
almost every pragma is allowed in a 'push' pragma
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/main.nim | 1 | ||||
-rwxr-xr-x | compiler/pragmas.nim | 477 | ||||
-rwxr-xr-x | compiler/semdata.nim | 1 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 2 |
4 files changed, 254 insertions, 227 deletions
diff --git a/compiler/main.nim b/compiler/main.nim index 9aefa3eb3..dabd5309b 100755 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -259,6 +259,7 @@ proc MainCommand = gCmd = cmdDoc LoadConfigs(DocConfig) wantMainModule() + DefineSymbol("nimdoc") CommandDoc2() of "rst2html": gCmd = cmdRst2html diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index f874a0acf..8f06beecd 100755 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -262,11 +262,11 @@ proc processNote(c: PContext, n: PNode) = else: invalidPragma(n) -proc processOption(c: PContext, n: PNode) = - if n.kind != nkExprColonExpr: invalidPragma(n) +proc processOption(c: PContext, n: PNode): bool = + if n.kind != nkExprColonExpr: result = true elif n.sons[0].kind == nkBracketExpr: processNote(c, n) - elif n.sons[0].kind != nkIdent: invalidPragma(n) - else: + elif n.sons[0].kind != nkIdent: result = true + else: var sw = whichKeyword(n.sons[0].ident) case sw of wChecks: OnOff(c, n, checksOptions) @@ -307,9 +307,11 @@ proc processOption(c: PContext, n: PNode) = else: LocalError(n.info, errNoneSpeedOrSizeExpected) of wImplicitStatic: OnOff(c, n, {optImplicitStatic}) of wPatterns: OnOff(c, n, {optPatterns}) - else: LocalError(n.info, errOptionExpected) + else: result = true proc processPush(c: PContext, n: PNode, start: int) = + if n.sons[start-1].kind == nkExprColonExpr: + LocalError(n.info, errGenerated, "':' after 'push' not supported") var x = newOptionEntry() var y = POptionEntry(c.optionStack.tail) x.options = gOptions @@ -318,15 +320,18 @@ proc processPush(c: PContext, n: PNode, start: int) = x.notes = gNotes append(c.optionStack, x) for i in countup(start, sonsLen(n) - 1): - processOption(c, n.sons[i]) - #liMessage(n.info, warnUser, ropeToStr(optionsToStr(gOptions))); + if processOption(c, n.sons[i]): + # simply store it somehwere: + if x.otherPragmas.isNil: + x.otherPragmas = newNodeI(nkPragma, n.info) + x.otherPragmas.add n.sons[i] + #LocalError(n.info, errOptionExpected) proc processPop(c: PContext, n: PNode) = if c.optionStack.counter <= 1: LocalError(n.info, errAtPopWithoutPush) else: gOptions = POptionEntry(c.optionStack.tail).options - #liMessage(n.info, warnUser, ropeToStr(optionsToStr(gOptions))); gNotes = POptionEntry(c.optionStack.tail).notes remove(c.optionStack, c.optionStack.tail) @@ -481,227 +486,240 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) = else: invalidPragma(n) -proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) = - if n == nil: return - for i in countup(0, sonsLen(n) - 1): - var it = n.sons[i] - var key = if it.kind == nkExprColonExpr: it.sons[0] else: it - if key.kind == nkIdent: - var userPragma = StrTableGet(c.userPragmas, key.ident) - if userPragma != nil: - inc c.InstCounter - if c.InstCounter > 100: - GlobalError(it.info, errRecursiveDependencyX, userPragma.name.s) - pragma(c, sym, userPragma.ast, validPragmas) - dec c.InstCounter - else: - var k = whichKeyword(key.ident) - if k in validPragmas: - case k - of wExportc: - makeExternExport(sym, getOptionalStr(c, it, sym.name.s)) - incl(sym.flags, sfUsed) # avoid wrong hints - of wImportc: makeExternImport(sym, getOptionalStr(c, it, sym.name.s)) - of wImportCompilerProc: - processImportCompilerProc(sym, getOptionalStr(c, it, sym.name.s)) - of wExtern: setExternName(sym, expectStrLit(c, it)) - of wImmediate: - if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate) - else: invalidPragma(it) - of wDirty: - if sym.kind == skTemplate: incl(sym.flags, sfDirty) - else: invalidPragma(it) - of wImportCpp: - processImportCpp(sym, getOptionalStr(c, it, sym.name.s)) - of wImportObjC: - processImportObjC(sym, getOptionalStr(c, it, sym.name.s)) - of wAlign: - if sym.typ == nil: invalidPragma(it) - var align = expectIntLit(c, it) - if not IsPowerOfTwo(align) and align != 0: - LocalError(it.info, errPowerOfTwoExpected) - else: - sym.typ.align = align - of wSize: - if sym.typ == nil: invalidPragma(it) - var size = expectIntLit(c, it) - if not IsPowerOfTwo(size) or size <= 0 or size > 8: - LocalError(it.info, errPowerOfTwoExpected) - else: - sym.typ.size = size - of wNodecl: - noVal(it) - incl(sym.loc.Flags, lfNoDecl) - of wPure, wNoStackFrame: - noVal(it) - if sym != nil: incl(sym.flags, sfPure) - of wVolatile: - noVal(it) - incl(sym.flags, sfVolatile) - of wRegister: - noVal(it) - incl(sym.flags, sfRegister) - of wThreadVar: - noVal(it) - incl(sym.flags, sfThread) - of wDeadCodeElim: pragmaDeadCodeElim(c, it) - of wMagic: processMagic(c, it, sym) - of wCompileTime: - noVal(it) - incl(sym.flags, sfCompileTime) - incl(sym.loc.Flags, lfNoDecl) - of wGlobal: - noVal(it) - incl(sym.flags, sfGlobal) - of wMerge: - noval(it) - incl(sym.flags, sfMerge) - of wHeader: - var lib = getLib(c, libHeader, getStrLitNode(c, it)) - addToLib(lib, sym) - incl(sym.flags, sfImportc) - incl(sym.loc.flags, lfHeader) - incl(sym.loc.Flags, lfNoDecl) - # implies nodecl, because otherwise header would not make sense - if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s) - of wDestructor: - if sym.typ.sons.len == 2: - sym.flags.incl sfDestructor - else: - invalidPragma(it) - of wNosideeffect: - noVal(it) - incl(sym.flags, sfNoSideEffect) - if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect) - of wSideEffect: - noVal(it) - incl(sym.flags, sfSideEffect) - of wNoReturn: - noVal(it) - incl(sym.flags, sfNoReturn) - of wDynLib: - processDynLib(c, it, sym) - of wCompilerProc: - noVal(it) # compilerproc may not get a string! - makeExternExport(sym, sym.name.s) - incl(sym.flags, sfCompilerProc) - incl(sym.flags, sfUsed) # suppress all those stupid warnings - registerCompilerProc(sym) - of wProcvar: - noVal(it) - incl(sym.flags, sfProcVar) - of wDeprecated: - noVal(it) - if sym != nil: incl(sym.flags, sfDeprecated) - else: incl(c.module.flags, sfDeprecated) - of wVarargs: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfVarargs) - of wBorrow: - noVal(it) - incl(sym.flags, sfBorrow) - of wFinal: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfFinal) - of wInheritable: - noVal(it) - if sym.typ == nil or tfFinal in sym.typ.flags: invalidPragma(it) - else: incl(sym.typ.flags, tfInheritable) - of wAcyclic: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfAcyclic) - of wShallow: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfShallow) - of wThread: - noVal(it) - incl(sym.flags, sfThread) - incl(sym.flags, sfProcVar) - if sym.typ != nil: incl(sym.typ.flags, tfThread) - of wHint: Message(it.info, hintUser, expectStrLit(c, it)) - of wWarning: Message(it.info, warnUser, expectStrLit(c, it)) - of wError: - if sym != nil and sym.isRoutine: - # This is subtle but correct: the error *statement* is only - # allowed for top level statements. Seems to be easier than - # distinguishing properly between - # ``proc p() {.error}`` and ``proc p() = {.error: "msg".}`` - noVal(it) - incl(sym.flags, sfError) - else: - LocalError(it.info, errUser, expectStrLit(c, it)) - of wFatal: Fatal(it.info, errUser, expectStrLit(c, it)) - of wDefine: processDefine(c, it) - of wUndef: processUndef(c, it) - of wCompile: processCompile(c, it) - of wLink: processCommonLink(c, it, linkNormal) - of wLinkSys: processCommonLink(c, it, linkSys) - of wPassL: extccomp.addLinkOption(expectStrLit(c, it)) - of wPassC: extccomp.addCompileOption(expectStrLit(c, it)) - of wBreakpoint: PragmaBreakpoint(c, it) - of wWatchpoint: PragmaWatchpoint(c, it) - of wPush: - processPush(c, n, i + 1) - break - of wPop: processPop(c, it) - of wPragma: - processPragma(c, n, i) - break - of wDiscardable: - noVal(it) - if sym != nil: incl(sym.flags, sfDiscardable) - of wNoInit: - noVal(it) - if sym != nil: incl(sym.flags, sfNoInit) - of wHoist: - noVal(it) - if sym != nil: incl(sym.flags, sfHoist) - of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, - wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, - wLinedir, wStacktrace, wLinetrace, wOptimization, - wCallConv, - wDebugger, wProfiler, wFloatChecks, wNanChecks, wInfChecks, - wPatterns: - processOption(c, it) # calling conventions (boring...): - of firstCallConv..lastCallConv: - assert(sym != nil) - if sym.typ == nil: invalidPragma(it) - else: sym.typ.callConv = wordToCallConv(k) - of wEmit: PragmaEmit(c, it) - of wUnroll: PragmaUnroll(c, it) - of wLinearScanEnd: PragmaLinearScanEnd(c, it) - of wEffects: - # is later processed in effect analysis: - noVal(it) - of wIncompleteStruct: - noVal(it) - if sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfIncompleteStruct) - of wByRef: - noVal(it) - if sym == nil or sym.typ == nil: - processOption(c, it) - else: - incl(sym.typ.flags, tfByRef) - of wByCopy: - noVal(it) - if sym.kind != skType or sym.typ == nil: invalidPragma(it) - else: incl(sym.typ.flags, tfByCopy) - of wInject, wGenSym: - # We check for errors, but do nothing with these pragmas otherwise - # as they are handled directly in 'evalTemplate'. - noVal(it) - if sym == nil: invalidPragma(it) - of wLine: PragmaLine(c, it) - of wRaises, wTags: pragmaRaisesOrTags(c, it) +proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, + validPragmas: TSpecialWords): bool = + var it = n.sons[i] + var key = if it.kind == nkExprColonExpr: it.sons[0] else: it + if key.kind == nkIdent: + var userPragma = StrTableGet(c.userPragmas, key.ident) + if userPragma != nil: + inc c.InstCounter + if c.InstCounter > 100: + GlobalError(it.info, errRecursiveDependencyX, userPragma.name.s) + pragma(c, sym, userPragma.ast, validPragmas) + dec c.InstCounter + else: + var k = whichKeyword(key.ident) + if k in validPragmas: + case k + of wExportc: + makeExternExport(sym, getOptionalStr(c, it, sym.name.s)) + incl(sym.flags, sfUsed) # avoid wrong hints + of wImportc: makeExternImport(sym, getOptionalStr(c, it, sym.name.s)) + of wImportCompilerProc: + processImportCompilerProc(sym, getOptionalStr(c, it, sym.name.s)) + of wExtern: setExternName(sym, expectStrLit(c, it)) + of wImmediate: + if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate) + else: invalidPragma(it) + of wDirty: + if sym.kind == skTemplate: incl(sym.flags, sfDirty) else: invalidPragma(it) + of wImportCpp: + processImportCpp(sym, getOptionalStr(c, it, sym.name.s)) + of wImportObjC: + processImportObjC(sym, getOptionalStr(c, it, sym.name.s)) + of wAlign: + if sym.typ == nil: invalidPragma(it) + var align = expectIntLit(c, it) + if not IsPowerOfTwo(align) and align != 0: + LocalError(it.info, errPowerOfTwoExpected) + else: + sym.typ.align = align + of wSize: + if sym.typ == nil: invalidPragma(it) + var size = expectIntLit(c, it) + if not IsPowerOfTwo(size) or size <= 0 or size > 8: + LocalError(it.info, errPowerOfTwoExpected) + else: + sym.typ.size = size + of wNodecl: + noVal(it) + incl(sym.loc.Flags, lfNoDecl) + of wPure, wNoStackFrame: + noVal(it) + if sym != nil: incl(sym.flags, sfPure) + of wVolatile: + noVal(it) + incl(sym.flags, sfVolatile) + of wRegister: + noVal(it) + incl(sym.flags, sfRegister) + of wThreadVar: + noVal(it) + incl(sym.flags, sfThread) + of wDeadCodeElim: pragmaDeadCodeElim(c, it) + of wMagic: processMagic(c, it, sym) + of wCompileTime: + noVal(it) + incl(sym.flags, sfCompileTime) + incl(sym.loc.Flags, lfNoDecl) + of wGlobal: + noVal(it) + incl(sym.flags, sfGlobal) + of wMerge: + noval(it) + incl(sym.flags, sfMerge) + of wHeader: + var lib = getLib(c, libHeader, getStrLitNode(c, it)) + addToLib(lib, sym) + incl(sym.flags, sfImportc) + incl(sym.loc.flags, lfHeader) + incl(sym.loc.Flags, lfNoDecl) + # implies nodecl, because otherwise header would not make sense + if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s) + of wDestructor: + if sym.typ.sons.len == 2: + sym.flags.incl sfDestructor + else: + invalidPragma(it) + of wNosideeffect: + noVal(it) + incl(sym.flags, sfNoSideEffect) + if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect) + of wSideEffect: + noVal(it) + incl(sym.flags, sfSideEffect) + of wNoReturn: + noVal(it) + incl(sym.flags, sfNoReturn) + of wDynLib: + processDynLib(c, it, sym) + of wCompilerProc: + noVal(it) # compilerproc may not get a string! + makeExternExport(sym, sym.name.s) + incl(sym.flags, sfCompilerProc) + incl(sym.flags, sfUsed) # suppress all those stupid warnings + registerCompilerProc(sym) + of wProcvar: + noVal(it) + incl(sym.flags, sfProcVar) + of wDeprecated: + noVal(it) + if sym != nil: incl(sym.flags, sfDeprecated) + else: incl(c.module.flags, sfDeprecated) + of wVarargs: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfVarargs) + of wBorrow: + noVal(it) + incl(sym.flags, sfBorrow) + of wFinal: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfFinal) + of wInheritable: + noVal(it) + if sym.typ == nil or tfFinal in sym.typ.flags: invalidPragma(it) + else: incl(sym.typ.flags, tfInheritable) + of wAcyclic: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfAcyclic) + of wShallow: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfShallow) + of wThread: + noVal(it) + incl(sym.flags, sfThread) + incl(sym.flags, sfProcVar) + if sym.typ != nil: incl(sym.typ.flags, tfThread) + of wHint: Message(it.info, hintUser, expectStrLit(c, it)) + of wWarning: Message(it.info, warnUser, expectStrLit(c, it)) + of wError: + if sym != nil and sym.isRoutine: + # This is subtle but correct: the error *statement* is only + # allowed for top level statements. Seems to be easier than + # distinguishing properly between + # ``proc p() {.error}`` and ``proc p() = {.error: "msg".}`` + noVal(it) + incl(sym.flags, sfError) + else: + LocalError(it.info, errUser, expectStrLit(c, it)) + of wFatal: Fatal(it.info, errUser, expectStrLit(c, it)) + of wDefine: processDefine(c, it) + of wUndef: processUndef(c, it) + of wCompile: processCompile(c, it) + of wLink: processCommonLink(c, it, linkNormal) + of wLinkSys: processCommonLink(c, it, linkSys) + of wPassL: extccomp.addLinkOption(expectStrLit(c, it)) + of wPassC: extccomp.addCompileOption(expectStrLit(c, it)) + of wBreakpoint: PragmaBreakpoint(c, it) + of wWatchpoint: PragmaWatchpoint(c, it) + of wPush: + processPush(c, n, i + 1) + result = true + of wPop: processPop(c, it) + of wPragma: + processPragma(c, n, i) + result = true + of wDiscardable: + noVal(it) + if sym != nil: incl(sym.flags, sfDiscardable) + of wNoInit: + noVal(it) + if sym != nil: incl(sym.flags, sfNoInit) + of wHoist: + noVal(it) + if sym != nil: incl(sym.flags, sfHoist) + of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, + wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, + wLinedir, wStacktrace, wLinetrace, wOptimization, + wCallConv, + wDebugger, wProfiler, wFloatChecks, wNanChecks, wInfChecks, + wPatterns: + if processOption(c, it): + # calling conventions (boring...): + LocalError(it.info, errOptionExpected) + of firstCallConv..lastCallConv: + assert(sym != nil) + if sym.typ == nil: invalidPragma(it) + else: sym.typ.callConv = wordToCallConv(k) + of wEmit: PragmaEmit(c, it) + of wUnroll: PragmaUnroll(c, it) + of wLinearScanEnd: PragmaLinearScanEnd(c, it) + of wEffects: + # is later processed in effect analysis: + noVal(it) + of wIncompleteStruct: + noVal(it) + if sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfIncompleteStruct) + of wByRef: + noVal(it) + if sym == nil or sym.typ == nil: + if processOption(c, it): LocalError(it.info, errOptionExpected) + else: + incl(sym.typ.flags, tfByRef) + of wByCopy: + noVal(it) + if sym.kind != skType or sym.typ == nil: invalidPragma(it) + else: incl(sym.typ.flags, tfByCopy) + of wInject, wGenSym: + # We check for errors, but do nothing with these pragmas otherwise + # as they are handled directly in 'evalTemplate'. + noVal(it) + if sym == nil: invalidPragma(it) + of wLine: PragmaLine(c, it) + of wRaises, wTags: pragmaRaisesOrTags(c, it) else: invalidPragma(it) - else: processNote(c, it) + else: invalidPragma(it) + else: processNote(c, it) + +proc implictPragmas*(c: PContext, sym: PSym, n: PNode, + validPragmas: TSpecialWords) = if sym != nil and sym.kind != skModule: + var it = POptionEntry(c.optionstack.head) + while it != nil: + let o = it.otherPragmas + if not o.isNil: + for i in countup(0, sonsLen(o) - 1): + if singlePragma(c, sym, o, i, validPragmas): + InternalError(n.info, "implicitPragmas") + it = it.next.POptionEntry + if lfExportLib in sym.loc.flags and sfExportc notin sym.flags: LocalError(n.info, errDynlibRequiresExportc) var lib = POptionEntry(c.optionstack.tail).dynlib @@ -710,4 +728,9 @@ proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) = incl(sym.loc.flags, lfDynamicLib) addToLib(lib, sym) if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s) - + +proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) = + if n == nil: return + for i in countup(0, sonsLen(n) - 1): + if singlePragma(c, sym, n, i, validPragmas): break + implictPragmas(c, sym, n, validPragmas) diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 57721bdc0..4ead9cf13 100755 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -22,6 +22,7 @@ type defaultCC*: TCallingConvention dynlib*: PLib Notes*: TNoteKinds + otherPragmas*: PNode # every pragma can be pushed POptionEntry* = ref TOptionEntry PProcCon* = ref TProcCon diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index a08c39ce6..52d922b2d 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -758,6 +758,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, addInterfaceDeclAt(c, s, c.tab.tos - 2) if n.sons[pragmasPos].kind != nkEmpty: pragma(c, s, n.sons[pragmasPos], validPragmas) + else: + implictPragmas(c, s, n, validPragmas) else: if n.sons[pragmasPos].kind != nkEmpty: LocalError(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc) |