From 2c9e56a783e36b0f9db3f2f73d76c910f36a9ffd Mon Sep 17 00:00:00 2001 From: cooldome Date: Tue, 9 Jan 2018 14:25:22 +0000 Subject: Implement custom annotations (#6987) --- compiler/pragmas.nim | 112 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 72 insertions(+), 40 deletions(-) (limited to 'compiler/pragmas.nim') diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index bdaecf91d..b6229796f 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -17,6 +17,7 @@ import const FirstCallConv* = wNimcall LastCallConv* = wNoconv + nkPragmaCallKinds = {nkExprColonExpr, nkCall, nkCallStrLit} const procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, @@ -29,7 +30,7 @@ const converterPragmas* = procPragmas methodPragmas* = procPragmas+{wBase}-{wImportCpp} templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty, - wDelegator, wExportNims, wUsed} + wDelegator, wExportNims, wUsed, wPragma} macroPragmas* = {FirstCallConv..LastCallConv, wImmediate, wImportc, wExportc, wNodecl, wMagic, wNosideeffect, wCompilerProc, wCore, wDeprecated, wExtern, wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wDelegator, @@ -74,7 +75,7 @@ proc getPragmaVal*(procAst: PNode; name: TSpecialWord): PNode = let p = procAst[pragmasPos] if p.kind == nkEmpty: return nil for it in p: - if it.kind == nkExprColonExpr and it[0].kind == nkIdent and + if it.kind in nkPragmaCallKinds and it.len == 2 and it[0].kind == nkIdent and it[0].ident.id == ord(name): return it[1] @@ -89,7 +90,7 @@ proc pragmaAsm*(c: PContext, n: PNode): char = if n != nil: for i in countup(0, sonsLen(n) - 1): let it = n.sons[i] - if it.kind == nkExprColonExpr and it.sons[0].kind == nkIdent: + if it.kind in nkPragmaCallKinds and it.len == 2 and it.sons[0].kind == nkIdent: case whichKeyword(it.sons[0].ident) of wSubsChar: if it.sons[1].kind == nkCharLit: result = chr(int(it.sons[1].intVal)) @@ -151,7 +152,7 @@ proc newEmptyStrNode(n: PNode): PNode {.noinline.} = result.strVal = "" proc getStrLitNode(c: PContext, n: PNode): PNode = - if n.kind != nkExprColonExpr: + if n.kind notin nkPragmaCallKinds or n.len != 2: localError(n.info, errStringLiteralExpected) # error correction: result = newEmptyStrNode(n) @@ -168,7 +169,7 @@ proc expectStrLit(c: PContext, n: PNode): string = result = getStrLitNode(c, n).strVal proc expectIntLit(c: PContext, n: PNode): int = - if n.kind != nkExprColonExpr: + if n.kind notin nkPragmaCallKinds or n.len != 2: localError(n.info, errIntLiteralExpected) else: n.sons[1] = c.semConstExpr(c, n.sons[1]) @@ -177,7 +178,7 @@ proc expectIntLit(c: PContext, n: PNode): int = else: localError(n.info, errIntLiteralExpected) proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string = - if n.kind == nkExprColonExpr: result = expectStrLit(c, n) + if n.kind in nkPragmaCallKinds: result = expectStrLit(c, n) else: result = defaultStr proc processCodegenDecl(c: PContext, n: PNode, sym: PSym) = @@ -186,7 +187,7 @@ proc processCodegenDecl(c: PContext, n: PNode, sym: PSym) = proc processMagic(c: PContext, n: PNode, s: PSym) = #if sfSystemModule notin c.module.flags: # liMessage(n.info, errMagicOnlyInSystem) - if n.kind != nkExprColonExpr: + if n.kind notin nkPragmaCallKinds or n.len != 2: localError(n.info, errStringLiteralExpected) return var v: string @@ -204,7 +205,7 @@ proc wordToCallConv(sw: TSpecialWord): TCallingConvention = result = TCallingConvention(ord(ccDefault) + ord(sw) - ord(wNimcall)) proc isTurnedOn(c: PContext, n: PNode): bool = - if n.kind == nkExprColonExpr: + if n.kind in nkPragmaCallKinds and n.len == 2: let x = c.semConstBoolExpr(c, n.sons[1]) n.sons[1] = x if x.kind == nkIntLit: return x.intVal != 0 @@ -223,7 +224,7 @@ proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) = else: excl(c.module.flags, flag) proc processCallConv(c: PContext, n: PNode) = - if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): + if n.kind in nkPragmaCallKinds and n.len == 2 and n.sons[1].kind == nkIdent: var sw = whichKeyword(n.sons[1].ident) case sw of FirstCallConv..LastCallConv: @@ -244,7 +245,7 @@ proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib = result.isOverriden = options.isDynlibOverride(path.strVal) proc expectDynlibNode(c: PContext, n: PNode): PNode = - if n.kind != nkExprColonExpr: + if n.kind notin nkPragmaCallKinds or n.len != 2: localError(n.info, errStringLiteralExpected) # error correction: result = newEmptyStrNode(n) @@ -264,7 +265,7 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) = if not lib.isOverriden: c.optionStack[^1].dynlib = lib else: - if n.kind == nkExprColonExpr: + if n.kind in nkPragmaCallKinds: var lib = getLib(c, libDynamic, expectDynlibNode(c, n)) if not lib.isOverriden: addToLib(lib, sym) @@ -279,7 +280,7 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) = sym.typ.callConv = ccCDecl proc processNote(c: PContext, n: PNode) = - if (n.kind == nkExprColonExpr) and (sonsLen(n) == 2) and + if (n.kind in nkPragmaCallKinds) and (sonsLen(n) == 2) and (n.sons[0].kind == nkBracketExpr) and (n.sons[0].sons.len == 2) and (n.sons[0].sons[1].kind == nkIdent) and @@ -307,7 +308,7 @@ proc processNote(c: PContext, n: PNode) = invalidPragma(n) proc processOption(c: PContext, n: PNode): bool = - if n.kind != nkExprColonExpr: result = true + if n.kind notin nkPragmaCallKinds or n.len != 2: result = true elif n.sons[0].kind == nkBracketExpr: processNote(c, n) elif n.sons[0].kind != nkIdent: result = true else: @@ -355,8 +356,8 @@ proc processOption(c: PContext, n: PNode): bool = 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") + if n.sons[start-1].kind in nkPragmaCallKinds: + localError(n.info, errGenerated, "'push' can't have arguments") var x = newOptionEntry() var y = c.optionStack[^1] x.options = gOptions @@ -381,14 +382,14 @@ proc processPop(c: PContext, n: PNode) = c.optionStack.setLen(c.optionStack.len - 1) proc processDefine(c: PContext, n: PNode) = - if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): + if (n.kind in nkPragmaCallKinds and n.len == 2) and (n.sons[1].kind == nkIdent): defineSymbol(n.sons[1].ident.s) message(n.info, warnDeprecated, "define") else: invalidPragma(n) proc processUndef(c: PContext, n: PNode) = - if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent): + if (n.kind in nkPragmaCallKinds and n.len == 2) and (n.sons[1].kind == nkIdent): undefSymbol(n.sons[1].ident.s) message(n.info, warnDeprecated, "undef") else: @@ -420,7 +421,7 @@ proc processCompile(c: PContext, n: PNode) = localError(n.info, errStringLiteralExpected) result = "" - let it = if n.kind == nkExprColonExpr: n.sons[1] else: n + let it = if n.kind in nkPragmaCallKinds and n.len == 2: n.sons[1] else: n if it.kind == nkPar and it.len == 2: let s = getStrLit(c, it, 0) let dest = getStrLit(c, it, 1) @@ -453,7 +454,7 @@ proc pragmaBreakpoint(c: PContext, n: PNode) = discard getOptionalStr(c, n, "") proc pragmaWatchpoint(c: PContext, n: PNode) = - if n.kind == nkExprColonExpr: + if n.kind in nkPragmaCallKinds and n.len == 2: n.sons[1] = c.semExpr(c, n.sons[1]) else: invalidPragma(n) @@ -494,7 +495,7 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode = result = newNode(nkAsmStmt, n.info) proc pragmaEmit(c: PContext, n: PNode) = - if n.kind != nkExprColonExpr: + if n.kind notin nkPragmaCallKinds or n.len != 2: localError(n.info, errStringLiteralExpected) else: let n1 = n[1] @@ -512,12 +513,12 @@ proc pragmaEmit(c: PContext, n: PNode) = localError(n.info, errStringLiteralExpected) proc noVal(n: PNode) = - if n.kind == nkExprColonExpr: invalidPragma(n) + if n.kind in nkPragmaCallKinds and n.len > 1: invalidPragma(n) proc pragmaUnroll(c: PContext, n: PNode) = if c.p.nestedLoopCounter <= 0: invalidPragma(n) - elif n.kind == nkExprColonExpr: + elif n.kind in nkPragmaCallKinds and n.len == 2: var unrollFactor = expectIntLit(c, n) if unrollFactor <% 32: n.sons[1] = newIntNode(nkIntLit, unrollFactor) @@ -525,10 +526,11 @@ proc pragmaUnroll(c: PContext, n: PNode) = invalidPragma(n) proc pragmaLine(c: PContext, n: PNode) = - if n.kind == nkExprColonExpr: + if n.kind in nkPragmaCallKinds and n.len == 2: n.sons[1] = c.semConstExpr(c, n.sons[1]) let a = n.sons[1] if a.kind == nkPar: + # unpack the tuple var x = a.sons[0] var y = a.sons[1] if x.kind == nkExprColonExpr: x = x.sons[1] @@ -549,7 +551,7 @@ proc pragmaLine(c: PContext, n: PNode) = proc processPragma(c: PContext, n: PNode, i: int) = var it = n.sons[i] - if it.kind != nkExprColonExpr: invalidPragma(n) + if it.kind notin nkPragmaCallKinds and it.len == 2: invalidPragma(n) elif it.sons[0].kind != nkIdent: invalidPragma(n) elif it.sons[1].kind != nkIdent: invalidPragma(n) @@ -566,7 +568,7 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) = localError(x.info, errGenerated, "invalid type for raises/tags list") x.typ = t - if n.kind == nkExprColonExpr: + if n.kind in nkPragmaCallKinds and n.len == 2: let it = n.sons[1] if it.kind notin {nkCurly, nkBracket}: processExc(c, it) @@ -576,7 +578,7 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) = invalidPragma(n) proc pragmaLockStmt(c: PContext; it: PNode) = - if it.kind != nkExprColonExpr: + if it.kind notin nkPragmaCallKinds or it.len != 2: invalidPragma(it) else: let n = it[1] @@ -587,7 +589,7 @@ proc pragmaLockStmt(c: PContext; it: PNode) = n.sons[i] = c.semExpr(c, n.sons[i]) proc pragmaLocks(c: PContext, it: PNode): TLockLevel = - if it.kind != nkExprColonExpr: + if it.kind notin nkPragmaCallKinds or it.len != 2: invalidPragma(it) else: case it[1].kind @@ -604,7 +606,7 @@ proc pragmaLocks(c: PContext, it: PNode): TLockLevel = result = TLockLevel(x) proc typeBorrow(sym: PSym, n: PNode) = - if n.kind == nkExprColonExpr: + if n.kind in nkPragmaCallKinds and n.len == 2: let it = n.sons[1] if it.kind != nkAccQuoted: localError(n.info, "a type can only borrow `.` for now") @@ -624,7 +626,7 @@ proc deprecatedStmt(c: PContext; pragma: PNode) = if pragma.kind != nkBracket: localError(pragma.info, "list of key:value pairs expected"); return for n in pragma: - if n.kind in {nkExprColonExpr, nkExprEqExpr}: + if n.kind in nkPragmaCallKinds and n.len == 2: let dest = qualifiedLookUp(c, n[1], {checkUndeclared}) if dest == nil or dest.kind in routineKinds: localError(n.info, warnUser, "the .deprecated pragma is unreliable for routines") @@ -638,7 +640,7 @@ proc deprecatedStmt(c: PContext; pragma: PNode) = localError(n.info, "key:value pair expected") proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym = - if it.kind != nkExprColonExpr: + if it.kind notin nkPragmaCallKinds or it.len != 2: invalidPragma(it); return let n = it[1] if n.kind == nkSym: @@ -655,13 +657,36 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym = else: result = qualifiedLookUp(c, n, {checkUndeclared}) +proc semCustomPragma(c: PContext, n: PNode): PNode = + assert(n.kind in nkPragmaCallKinds + {nkIdent}) + + if n.kind == nkIdent: + result = newTree(nkCall, n) + elif n.kind == nkExprColonExpr: + # pragma: arg -> pragma(arg) + result = newTree(nkCall, n[0], n[1]) + else: + result = n + + result = c.semOverloadedCall(c, result, n, {skTemplate}, {}) + if sfCustomPragma notin result[0].sym.flags: + invalidPragma(n) + + if n.kind == nkIdent: + result = result[0] + elif n.kind == nkExprColonExpr: + result.kind = n.kind # pragma(arg) -> pragma: arg + 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 + var key = if it.kind in nkPragmaCallKinds and it.len > 1: it.sons[0] else: it if key.kind == nkBracketExpr: processNote(c, it) return + elif key.kind notin nkIdentKinds: + n.sons[i] = semCustomPragma(c, it) + return let ident = considerQuotedIdent(key) var userPragma = strTableGet(c.userPragmas, ident) if userPragma != nil: @@ -785,7 +810,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, of wExplain: sym.flags.incl sfExplain of wDeprecated: - if it.kind == nkExprColonExpr: deprecatedStmt(c, it) + if it.kind in nkPragmaCallKinds: deprecatedStmt(c, it) elif sym != nil: incl(sym.flags, sfDeprecated) else: incl(c.module.flags, sfDeprecated) of wVarargs: @@ -864,8 +889,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, result = true of wPop: processPop(c, it) of wPragma: - processPragma(c, n, i) - result = true + if not sym.isNil and sym.kind == skTemplate: + sym.flags.incl sfCustomPragma + else: + processPragma(c, n, i) + result = true of wDiscardable: noVal(it) if sym != nil: incl(sym.flags, sfDiscardable) @@ -939,7 +967,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, elif sym.typ == nil: invalidPragma(it) else: sym.typ.lockLevel = pragmaLocks(c, it) of wBitsize: - if sym == nil or sym.kind != skField or it.kind != nkExprColonExpr: + if sym == nil or sym.kind != skField: invalidPragma(it) else: sym.bitsize = expectIntLit(c, it) @@ -957,7 +985,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, if sym == nil: invalidPragma(it) else: magicsys.registerNimScriptSymbol(sym) of wInjectStmt: - if it.kind != nkExprColonExpr: + if it.kind notin nkPragmaCallKinds or it.len != 2: localError(it.info, errExprExpected) else: it.sons[1] = c.semExpr(c, it.sons[1]) @@ -968,10 +996,12 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, else: localError(it.info, "'experimental' pragma only valid as toplevel statement") of wThis: - if it.kind == nkExprColonExpr: + if it.kind in nkPragmaCallKinds and it.len == 2: c.selfName = considerQuotedIdent(it[1]) - else: + elif it.kind == nkIdent or it.len == 1: c.selfName = getIdent("self") + else: + localError(it.info, "'this' pragma is allowed to have zero or one arguments") of wNoRewrite: noVal(it) of wBase: @@ -987,7 +1017,9 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, else: sym.flags.incl sfUsed of wLiftLocals: discard else: invalidPragma(it) - else: invalidPragma(it) + else: + n.sons[i] = semCustomPragma(c, it) + proc implicitPragmas*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) = @@ -1015,7 +1047,7 @@ proc hasPragma*(n: PNode, pragma: TSpecialWord): bool = return false for p in n.sons: - var key = if p.kind == nkExprColonExpr: p[0] else: p + var key = if p.kind in nkPragmaCallKinds and p.len > 1: p[0] else: p if key.kind == nkIdent and whichKeyword(key.ident) == pragma: return true -- cgit 1.4.1-2-gfad0 From 27aab0be162de4cca6132b46c12d98ce9c83d60e Mon Sep 17 00:00:00 2001 From: cooldome Date: Thu, 18 Jan 2018 09:38:55 +0000 Subject: Custom pragmas in procs bug fix (#7086) --- compiler/ast.nim | 1 + compiler/pragmas.nim | 1 - compiler/semstmts.nim | 10 ++++++---- tests/pragmas/tcustom_pragma.nim | 10 ++++++++++ 4 files changed, 17 insertions(+), 5 deletions(-) (limited to 'compiler/pragmas.nim') diff --git a/compiler/ast.nim b/compiler/ast.nim index 69f2eb1c7..5c70bda18 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -979,6 +979,7 @@ const nkIdentKinds* = {nkIdent, nkSym, nkAccQuoted, nkOpenSymChoice, nkClosedSymChoice} + nkPragmaCallKinds* = {nkExprColonExpr, nkCall, nkCallStrLit} nkLiterals* = {nkCharLit..nkTripleStrLit} nkLambdaKinds* = {nkLambda, nkDo} declarativeDefs* = {nkProcDef, nkFuncDef, nkMethodDef, nkIteratorDef, nkConverterDef} diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index b6229796f..810c4c416 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -17,7 +17,6 @@ import const FirstCallConv* = wNimcall LastCallConv* = wNoconv - nkPragmaCallKinds = {nkExprColonExpr, nkCall, nkCallStrLit} const procPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl, diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index ccddabcbe..78833adad 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1143,7 +1143,7 @@ proc semProcAnnotation(c: PContext, prc: PNode; if n == nil or n.kind == nkEmpty: return for i in countup(0, n.len-1): var it = n.sons[i] - var key = if it.kind == nkExprColonExpr: it.sons[0] else: it + var key = if it.kind in nkPragmaCallKinds and it.len >= 1: it.sons[0] else: it let m = lookupMacro(c, key) if m == nil: if key.kind == nkIdent and key.ident.id == ord(wDelegator): @@ -1164,10 +1164,12 @@ proc semProcAnnotation(c: PContext, prc: PNode; if prc[pragmasPos].kind != nkEmpty and prc[pragmasPos].len == 0: prc.sons[pragmasPos] = emptyNode - if it.kind == nkExprColonExpr: - # pass pragma argument to the macro too: - x.add(it.sons[1]) + if it.kind in nkPragmaCallKinds and it.len > 1: + # pass pragma arguments to the macro too: + for i in 1.. Date: Tue, 30 Jan 2018 01:41:32 +0300 Subject: Fixes nimsuggest#78 (#7151) --- compiler/pragmas.nim | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'compiler/pragmas.nim') diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 810c4c416..cf289a506 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -658,7 +658,7 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym = proc semCustomPragma(c: PContext, n: PNode): PNode = assert(n.kind in nkPragmaCallKinds + {nkIdent}) - + if n.kind == nkIdent: result = newTree(nkCall, n) elif n.kind == nkExprColonExpr: @@ -667,14 +667,15 @@ proc semCustomPragma(c: PContext, n: PNode): PNode = else: result = n - result = c.semOverloadedCall(c, result, n, {skTemplate}, {}) - if sfCustomPragma notin result[0].sym.flags: + let r = c.semOverloadedCall(c, result, n, {skTemplate}, {}) + if r.isNil or sfCustomPragma notin r[0].sym.flags: invalidPragma(n) - - if n.kind == nkIdent: - result = result[0] - elif n.kind == nkExprColonExpr: - result.kind = n.kind # pragma(arg) -> pragma: arg + else: + result = r + if n.kind == nkIdent: + result = result[0] + elif n.kind == nkExprColonExpr: + result.kind = n.kind # pragma(arg) -> pragma: arg proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, validPragmas: TSpecialWords): bool = @@ -1016,7 +1017,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, else: sym.flags.incl sfUsed of wLiftLocals: discard else: invalidPragma(it) - else: + else: n.sons[i] = semCustomPragma(c, it) -- cgit 1.4.1-2-gfad0 From 212457f5e01d1c52db590da3b9d7f8dd538d9269 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 2 Feb 2018 12:53:38 +0100 Subject: the .deprecated pragma for procs now supports a user-definable deprecation message --- changelog.md | 9 +++++++++ compiler/pragmas.nim | 5 ++++- compiler/suggest.nim | 14 +++++++++++++- compiler/trees.nim | 2 +- lib/system.nim | 1 - 5 files changed, 27 insertions(+), 4 deletions(-) (limited to 'compiler/pragmas.nim') diff --git a/changelog.md b/changelog.md index c2211b510..a3f16738f 100644 --- a/changelog.md +++ b/changelog.md @@ -238,3 +238,12 @@ styledEcho "Red on Green.", resetStyle - Type inference for generic type parameters involving numeric types is now symetric. See [Generic type inference for numeric types](https://nim-lang.org/docs/manual.html#generics-generic-type-inference-fornumeric-types) for more information. +- The ``deprecated`` pragma now supports a user-definable warning message for procs. + +```nim + +proc bar {.deprecated: "use foo instead".} = + return + +bar() +``` diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index cf289a506..d52d8b614 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -810,7 +810,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, of wExplain: sym.flags.incl sfExplain of wDeprecated: - if it.kind in nkPragmaCallKinds: deprecatedStmt(c, it) + if sym != nil and sym.kind in routineKinds: + if it.kind in nkPragmaCallKinds: discard getStrLitNode(c, it) + incl(sym.flags, sfDeprecated) + elif it.kind in nkPragmaCallKinds: deprecatedStmt(c, it) elif sym != nil: incl(sym.flags, sfDeprecated) else: incl(c.module.flags, sfDeprecated) of wVarargs: diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 28ce3c591..af31495aa 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -33,6 +33,7 @@ # included from sigmatch.nim import algorithm, prefixmatches +from wordrecg import wDeprecated when defined(nimsuggest): import passes, tables # importer @@ -479,12 +480,23 @@ proc suggestSym*(info: TLineInfo; s: PSym; usageSym: var PSym; isDecl=true) {.in isDecl: suggestResult(symToSuggest(s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0)) +proc warnAboutDeprecated(info: TLineInfo; s: PSym) = + if s.kind in routineKinds: + let n = s.ast[pragmasPos] + if n.kind != nkEmpty: + for it in n: + if whichPragma(it) == wDeprecated and it.safeLen == 2 and + it[1].kind in {nkStrLit..nkTripleStrLit}: + message(info, warnDeprecated, it[1].strVal & "; " & s.name.s) + return + message(info, warnDeprecated, s.name.s) + proc markUsed(info: TLineInfo; s: PSym; usageSym: var PSym) = incl(s.flags, sfUsed) if s.kind == skEnumField and s.owner != nil: incl(s.owner.flags, sfUsed) if {sfDeprecated, sfError} * s.flags != {}: - if sfDeprecated in s.flags: message(info, warnDeprecated, s.name.s) + if sfDeprecated in s.flags: warnAboutDeprecated(info, s) if sfError in s.flags: localError(info, errWrongSymbolX, s.name.s) when defined(nimsuggest): suggestSym(info, s, usageSym, false) diff --git a/compiler/trees.nim b/compiler/trees.nim index 577ea75ee..f69108942 100644 --- a/compiler/trees.nim +++ b/compiler/trees.nim @@ -118,7 +118,7 @@ proc isRange*(n: PNode): bool {.inline.} = result = true proc whichPragma*(n: PNode): TSpecialWord = - let key = if n.kind == nkExprColonExpr: n.sons[0] else: n + let key = if n.kind in nkPragmaCallKinds and n.len > 0: n.sons[0] else: n if key.kind == nkIdent: result = whichKeyword(key.ident) proc unnestStmts(n, result: PNode) = diff --git a/lib/system.nim b/lib/system.nim index 079b06b48..63511f71c 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -3769,7 +3769,6 @@ proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} = # by ``assert``. type Hide = proc (msg: string) {.noinline, raises: [], noSideEffect, tags: [].} - {.deprecated: [THide: Hide].} Hide(raiseAssert)(msg) template assert*(cond: bool, msg = "") = -- cgit 1.4.1-2-gfad0 From fc967cc7151665a21be035a22e9432b80feb0b90 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Mon, 12 Feb 2018 16:40:15 +0100 Subject: custom pragmas: proper error handling --- compiler/pragmas.nim | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'compiler/pragmas.nim') diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index d52d8b614..4ed1cea24 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -657,15 +657,16 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym = result = qualifiedLookUp(c, n, {checkUndeclared}) proc semCustomPragma(c: PContext, n: PNode): PNode = - assert(n.kind in nkPragmaCallKinds + {nkIdent}) - if n.kind == nkIdent: result = newTree(nkCall, n) elif n.kind == nkExprColonExpr: # pragma: arg -> pragma(arg) result = newTree(nkCall, n[0], n[1]) - else: + elif n.kind in nkPragmaCallKinds + {nkIdent}: result = n + else: + invalidPragma(n) + return n let r = c.semOverloadedCall(c, result, n, {skTemplate}, {}) if r.isNil or sfCustomPragma notin r[0].sym.flags: -- cgit 1.4.1-2-gfad0 From 0a8684db4cf3aa5c6fe8bd1b3abad83a24ad33bf Mon Sep 17 00:00:00 2001 From: cooldome Date: Tue, 27 Feb 2018 02:03:49 +0000 Subject: User pragmas hide effect specs bug fix. Fixes #7216 (#7217) --- compiler/pragmas.nim | 32 +++++++++++++++++--------------- tests/pragmas/tuserpragma2.nim | 11 +++++++++++ 2 files changed, 28 insertions(+), 15 deletions(-) create mode 100644 tests/pragmas/tuserpragma2.nim (limited to 'compiler/pragmas.nim') diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 4ed1cea24..1b8078628 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -549,15 +549,13 @@ proc pragmaLine(c: PContext, n: PNode) = n.info = getInfoContext(-1) proc processPragma(c: PContext, n: PNode, i: int) = - var it = n.sons[i] + let it = n[i] if it.kind notin nkPragmaCallKinds and it.len == 2: invalidPragma(n) - elif it.sons[0].kind != nkIdent: invalidPragma(n) - elif it.sons[1].kind != nkIdent: invalidPragma(n) + elif it[0].kind != nkIdent: invalidPragma(n) + elif it[1].kind != nkIdent: invalidPragma(n) - var userPragma = newSym(skTemplate, it.sons[1].ident, nil, it.info) - var body = newNodeI(nkPragma, n.info) - for j in i+1 .. sonsLen(n)-1: addSon(body, n.sons[j]) - userPragma.ast = body + var userPragma = newSym(skTemplate, it[1].ident, nil, it.info) + userPragma.ast = newNode(nkPragma, n.info, n.sons[i+1..^1]) strTableAdd(c.userPragmas, userPragma) proc pragmaRaisesOrTags(c: PContext, n: PNode) = @@ -678,7 +676,7 @@ proc semCustomPragma(c: PContext, n: PNode): PNode = elif n.kind == nkExprColonExpr: result.kind = n.kind # pragma(arg) -> pragma: arg -proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, +proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, validPragmas: TSpecialWords): bool = var it = n.sons[i] var key = if it.kind in nkPragmaCallKinds and it.len > 1: it.sons[0] else: it @@ -691,13 +689,14 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int, let ident = considerQuotedIdent(key) var userPragma = strTableGet(c.userPragmas, ident) if userPragma != nil: + # number of pragmas increase/decrease with user pragma expansion inc c.instCounter if c.instCounter > 100: globalError(it.info, errRecursiveDependencyX, userPragma.name.s) + pragma(c, sym, userPragma.ast, validPragmas) - # ensure the pragma is also remember for generic instantiations in other - # modules: - n.sons[i] = userPragma.ast + n.sons[i..i] = userPragma.ast.sons # expand user pragma with its content + i.inc(userPragma.ast.len - 1) # inc by -1 is ok, user pragmas was empty dec c.instCounter else: var k = whichKeyword(ident) @@ -1032,9 +1031,11 @@ proc implicitPragmas*(c: PContext, sym: PSym, n: PNode, let o = it.otherPragmas if not o.isNil: pushInfoContext(n.info) - for i in countup(0, sonsLen(o) - 1): + var i = 0 + while i < o.len(): if singlePragma(c, sym, o, i, validPragmas): internalError(n.info, "implicitPragmas") + inc i popInfoContext() if lfExportLib in sym.loc.flags and sfExportc notin sym.flags: @@ -1059,9 +1060,10 @@ proc hasPragma*(n: PNode, pragma: TSpecialWord): bool = proc pragmaRec(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) = if n == nil: return - for i in countup(0, sonsLen(n) - 1): - if n.sons[i].kind == nkPragma: pragmaRec(c, sym, n.sons[i], validPragmas) - elif singlePragma(c, sym, n, i, validPragmas): break + var i = 0 + while i < n.len(): + if singlePragma(c, sym, n, i, validPragmas): break + inc i proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) = if n == nil: return diff --git a/tests/pragmas/tuserpragma2.nim b/tests/pragmas/tuserpragma2.nim new file mode 100644 index 000000000..bf8844e66 --- /dev/null +++ b/tests/pragmas/tuserpragma2.nim @@ -0,0 +1,11 @@ +discard """ + file: "tuserpragma2.nim" + line: 11 + errormsg: "can raise an unlisted exception: ref Exception" +""" + +# bug #7216 +{.pragma: my_pragma, raises: [].} + +proc test1 {.my_pragma.} = + raise newException(Exception, "msg") -- cgit 1.4.1-2-gfad0 From 9de05ec3e04e8a2321b29896fe9fa7db4c6e65f3 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 30 Mar 2018 02:32:13 +0200 Subject: further steps in implementing sink parameters; refs #7041 --- compiler/ast.nim | 2 + compiler/commands.nim | 2 + compiler/destroyer.nim | 157 +++++++++++++++++++++++++++++++++++++++++++--- compiler/msgs.nim | 5 +- compiler/options.nim | 7 ++- compiler/pragmas.nim | 8 ++- compiler/semobjconstr.nim | 2 +- compiler/wordrecg.nim | 4 +- lib/system.nim | 5 ++ lib/system/chcks.nim | 5 ++ 10 files changed, 177 insertions(+), 20 deletions(-) (limited to 'compiler/pragmas.nim') diff --git a/compiler/ast.nim b/compiler/ast.nim index a28a7e7e3..68bf95772 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -453,6 +453,8 @@ type nfPreventCg # this node should be ignored by the codegen nfBlockArg # this a stmtlist appearing in a call (e.g. a do block) nfFromTemplate # a top-level node returned from a template + nfPreventDestructor # prevent destructor injectsion for the node + # (but not necessarily its children) TNodeFlags* = set[TNodeFlag] TTypeFlag* = enum # keep below 32 for efficiency reasons (now: beyond that) diff --git a/compiler/commands.nim b/compiler/commands.nim index 766b78798..2e9b6f8db 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -257,6 +257,7 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool = of "rangechecks": result = contains(gOptions, optRangeCheck) of "boundchecks": result = contains(gOptions, optBoundsCheck) of "overflowchecks": result = contains(gOptions, optOverflowCheck) + of "movechecks": result = contains(gOptions, optMoveCheck) of "linedir": result = contains(gOptions, optLineDir) of "assertions", "a": result = contains(gOptions, optAssert) of "deadcodeelim": result = contains(gGlobalOptions, optDeadCodeElim) @@ -493,6 +494,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "rangechecks": processOnOffSwitch({optRangeCheck}, arg, pass, info) of "boundchecks": processOnOffSwitch({optBoundsCheck}, arg, pass, info) of "overflowchecks": processOnOffSwitch({optOverflowCheck}, arg, pass, info) + of "movechecks": processOnOffSwitch({optMoveCheck}, arg, pass, info) of "linedir": processOnOffSwitch({optLineDir}, arg, pass, info) of "assertions", "a": processOnOffSwitch({optAssert}, arg, pass, info) of "deadcodeelim": processOnOffSwitchG({optDeadCodeElim}, arg, pass, info) diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim index 55da69985..9acc89be4 100644 --- a/compiler/destroyer.nim +++ b/compiler/destroyer.nim @@ -89,11 +89,36 @@ ## tmp.bar)) ## destroy(tmp.bar) ## destroy(tmp.x); destroy(tmp.y) +## + +##[ +From https://github.com/nim-lang/Nim/wiki/Destructors + +Rule Pattern Transformed into +---- ------- ---------------- +1.1 var x: T; stmts var x: T; try stmts + finally: `=destroy`(x) +1.2 var x: sink T; stmts var x: sink T; stmts; ensureEmpty(x) +2 x = f() `=sink`(x, f()) +3 x = lastReadOf z `=sink`(x, z) +4.1 y = sinkParam `=sink`(y, sinkParam) +4.2 x = y `=`(x, y) # a copy +5.1 f_sink(g()) f_sink(g()) +5.2 f_sink(y) f_sink(copy y); # copy unless we can see it's the last read +5.3 f_sink(move y) f_sink(y); reset(y) # explicit moves empties 'y' +5.4 f_noSink(g()) var tmp = bitwiseCopy(g()); f(tmp); `=destroy`(tmp) + +Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently + not allowed as a local variable. + +``move`` builtin needs to be implemented. +XXX Think about nfPreventDestructor logic. +]## import intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees, - strutils, options, dfa, lowerings, rodread + strutils, options, dfa, lowerings, rodread, tables const InterestingSyms = {skVar, skResult, skLet} @@ -106,6 +131,14 @@ type tmpObj: PType tmp: PSym destroys, topLevelVars: PNode + toDropBit: Table[int, PSym] + +proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode = + # XXX why are temps fields in an object here? + let f = newSym(skField, getIdent(":d" & $c.tmpObj.n.len), c.owner, info) + f.typ = typ + rawAddField c.tmpObj, f + result = rawDirectAccess(c.tmp, f) proc isHarmlessVar*(s: PSym; c: Con): bool = # 's' is harmless if it used only once and its @@ -212,14 +245,44 @@ proc genDestroy(t: PType; dest: PNode): PNode = proc addTopVar(c: var Con; v: PNode) = c.topLevelVars.add newTree(nkIdentDefs, v, emptyNode, emptyNode) +proc dropBit(c: var Con; s: PSym): PSym = + result = c.toDropBit.getOrDefault(s.id) + assert result != nil + +proc registerDropBit(c: var Con; s: PSym) = + let result = newSym(skTemp, getIdent(s.name.s & "_AliveBit"), c.owner, s.info) + result.typ = getSysType(tyBool) + let trueVal = newIntTypeNode(nkIntLit, 1, result.typ) + c.topLevelVars.add newTree(nkIdentDefs, newSymNode result, emptyNode, trueVal) + c.toDropBit[s.id] = result + # generate: + # if not sinkParam_AliveBit: `=destroy`(sinkParam) + c.destroys.add newTree(nkIfStmt, + newTree(nkElifBranch, newSymNode result, genDestroy(s.typ, newSymNode s))) + proc p(n: PNode; c: var Con): PNode template recurse(n, dest) = for i in 0.. 0: c.addTopVar(newSymNode c.tmp) diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 09413128b..70504cfc9 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -134,7 +134,7 @@ type hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath, hintConditionAlwaysTrue, hintName, hintPattern, hintExecuting, hintLinking, hintDependency, - hintSource, hintStackTrace, hintGCStats, + hintSource, hintPerformance, hintStackTrace, hintGCStats, hintUser, hintUserRaw const @@ -438,6 +438,7 @@ const hintLinking: "", hintDependency: "$1", hintSource: "$1", + hintPerformance: "$1", hintStackTrace: "$1", hintGCStats: "$1", hintUser: "$1", @@ -460,7 +461,7 @@ const "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded", "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf", "Path", "CondTrue", "Name", "Pattern", "Exec", "Link", "Dependency", - "Source", "StackTrace", "GCStats", + "Source", "Performance", "StackTrace", "GCStats", "User", "UserRaw"] const diff --git a/compiler/options.nim b/compiler/options.nim index 65f5a6245..be13e15d7 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -25,7 +25,7 @@ type # please make sure we have under 32 options TOption* = enum # **keep binary compatible** optNone, optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck, optOverflowCheck, optNilCheck, - optNaNCheck, optInfCheck, + optNaNCheck, optInfCheck, optMoveCheck, optAssert, optLineDir, optWarns, optHints, optOptimizeSpeed, optOptimizeSize, optStackTrace, # stack tracing support optLineTrace, # line tracing support (includes stack tracing) @@ -119,13 +119,14 @@ var const ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck, - optOverflowCheck, optBoundsCheck, optAssert, optNaNCheck, optInfCheck} + optOverflowCheck, optBoundsCheck, optAssert, optNaNCheck, optInfCheck, + optMoveCheck} var gOptions*: TOptions = {optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck, optOverflowCheck, optAssert, optWarns, optHints, optStackTrace, optLineTrace, - optPatterns, optNilCheck} + optPatterns, optNilCheck, optMoveCheck} gGlobalOptions*: TGlobalOptions = {optThreadAnalysis} gExitcode*: int8 gCmd*: TCommands = cmdNone # the command diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 1b8078628..1295ee18d 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -40,7 +40,8 @@ const wTags, wLocks, wGcSafe, wExportNims, wUsed} exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe} stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks, - wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, + wBoundchecks, wOverflowchecks, wNilchecks, wMovechecks, wAssertions, + wWarnings, wHints, wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop, wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated, @@ -323,6 +324,7 @@ proc processOption(c: PContext, n: PNode): bool = of wFloatchecks: onOff(c, n, {optNaNCheck, optInfCheck}) of wNanChecks: onOff(c, n, {optNaNCheck}) of wInfChecks: onOff(c, n, {optInfCheck}) + of wMovechecks: onOff(c, n, {optMoveCheck}) of wAssertions: onOff(c, n, {optAssert}) of wWarnings: onOff(c, n, {optWarns}) of wHints: onOff(c, n, {optHints}) @@ -693,7 +695,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, inc c.instCounter if c.instCounter > 100: globalError(it.info, errRecursiveDependencyX, userPragma.name.s) - + pragma(c, sym, userPragma.ast, validPragmas) n.sons[i..i] = userPragma.ast.sons # expand user pragma with its content i.inc(userPragma.ast.len - 1) # inc by -1 is ok, user pragmas was empty @@ -906,7 +908,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, of wCodegenDecl: processCodegenDecl(c, it, sym) of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints, - wLinedir, wStacktrace, wLinetrace, wOptimization, + wLinedir, wStacktrace, wLinetrace, wOptimization, wMovechecks, wCallconv, wDebugger, wProfiler, wFloatchecks, wNanChecks, wInfChecks, wPatterns: diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim index 63a4eb99a..e2296a0d2 100644 --- a/compiler/semobjconstr.nim +++ b/compiler/semobjconstr.nim @@ -76,7 +76,7 @@ proc semConstrField(c: PContext, flags: TExprFlags, return initValue proc caseBranchMatchesExpr(branch, matched: PNode): bool = - for i in 0 .. (branch.len - 2): + for i in 0 .. branch.len-2: if exprStructuralEquivalent(branch[i], matched): return true diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index e458cad03..76d91d4e7 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -52,7 +52,7 @@ type wNimcall, wStdcall, wCdecl, wSafecall, wSyscall, wInline, wNoInline, wFastcall, wClosure, wNoconv, wOn, wOff, wChecks, wRangechecks, wBoundchecks, wOverflowchecks, wNilchecks, - wFloatchecks, wNanChecks, wInfChecks, + wFloatchecks, wNanChecks, wInfChecks, wMoveChecks, wAssertions, wPatterns, wWarnings, wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags, wDeadCodeElim, wSafecode, wPackage, wNoForward, wReorder, wNoRewrite, @@ -139,7 +139,7 @@ const "cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "closure", "noconv", "on", "off", "checks", "rangechecks", "boundchecks", "overflowchecks", "nilchecks", - "floatchecks", "nanchecks", "infchecks", + "floatchecks", "nanchecks", "infchecks", "movechecks", "assertions", "patterns", "warnings", "hints", "optimization", "raises", "writes", "reads", "size", "effects", "tags", diff --git a/lib/system.nim b/lib/system.nim index 7116f8818..7eda30276 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -617,6 +617,11 @@ type ## ## This is only raised if the ``segfaults.nim`` module was imported! +when defined(nimNewRuntime): + type + MoveError* = object of SystemError ## \ + ## Raised on attempts to re-sink an already consumed ``sink`` parameter. + {.deprecated: [TObject: RootObj, PObject: RootRef, TEffect: RootEffect, FTime: TimeEffect, FIO: IOEffect, FReadIO: ReadIOEffect, FWriteIO: WriteIOEffect, FExecIO: ExecIOEffect, diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim index 69b680dbd..d3651f659 100644 --- a/lib/system/chcks.nim +++ b/lib/system/chcks.nim @@ -52,6 +52,11 @@ proc chckNil(p: pointer) = if p == nil: sysFatal(NilAccessError, "attempt to write to a nil address") +when defined(nimNewRuntime): + proc chckMove(b: bool) {.compilerproc.} = + if not b: + sysFatal(MoveError, "attempt to access an object that was moved") + proc chckNilDisp(p: pointer) {.compilerproc.} = if p == nil: sysFatal(NilAccessError, "cannot dispatch; dispatcher is nil") -- cgit 1.4.1-2-gfad0 From d8373622165f9dbdf12eef8c81204f35a376ff76 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Tue, 3 Apr 2018 10:25:20 +0200 Subject: C codegen: preparations for different seq and string implementations --- compiler/ccgexprs.nim | 30 +++++------------- compiler/ccgliterals.nim | 81 ++++++++++++++++++++++++++++++++++++++++++++++++ compiler/ccgtypes.nim | 13 ++++---- compiler/cgen.nim | 17 +++++++--- compiler/cgendata.nim | 3 +- compiler/pragmas.nim | 2 +- lib/core/seqs.nim | 6 ++-- lib/core/strs.nim | 7 ++--- 8 files changed, 116 insertions(+), 43 deletions(-) create mode 100644 compiler/ccgliterals.nim (limited to 'compiler/pragmas.nim') diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 471f36d89..6ee7d698e 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -30,12 +30,6 @@ proc intLiteral(i: BiggestInt): Rope = else: result = ~"(IL64(-9223372036854775807) - IL64(1))" -proc getStrLit(m: BModule, s: string): Rope = - discard cgsym(m, "TGenericSeq") - result = getTempName(m) - addf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n", - [result, makeCString(s), rope(len(s))]) - proc genLiteral(p: BProc, n: PNode, ty: PType): Rope = if ty == nil: internalError(n.info, "genLiteral: ty is nil") case n.kind @@ -67,19 +61,9 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope = of nkStrLit..nkTripleStrLit: case skipTypes(ty, abstractVarRange).kind of tyNil: - result = ropecg(p.module, "((#NimStringDesc*) NIM_NIL)", []) + result = genNilStringLiteral(p.module, n.info) of tyString: - if n.strVal.isNil: - result = ropecg(p.module, "((#NimStringDesc*) NIM_NIL)", []) - else: - let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels) - if id == p.module.labels: - # string literal not found in the cache: - result = ropecg(p.module, "((#NimStringDesc*) &$1)", - [getStrLit(p.module, n.strVal)]) - else: - result = ropecg(p.module, "((#NimStringDesc*) &$1$2)", - [p.module.tmpBase, rope(id)]) + result = genStringLiteral(p.module, n) else: if n.strVal.isNil: result = rope("NIM_NIL") else: result = makeCString(n.strVal) @@ -823,16 +807,16 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym) = genInExprAux(p, it, u, v, test) let id = nodeTableTestOrSet(p.module.dataCache, newStrNode(nkStrLit, field.name.s), p.module.labels) - let strLit = if id == p.module.labels: getStrLit(p.module, field.name.s) + let strLit = if id == p.module.labels: genStringLiteralDataOnly(p.module, field.name.s, e.info) else: p.module.tmpBase & rope(id) if op.magic == mNot: linefmt(p, cpsStmts, - "if ($1) #raiseFieldError(((#NimStringDesc*) &$2));$n", - rdLoc(test), strLit) + "if ($1) #raiseFieldError($2);$n", + rdLoc(test), genStringLiteralFromData(p.module, strLit, e.info)) else: linefmt(p, cpsStmts, - "if (!($1)) #raiseFieldError(((#NimStringDesc*) &$2));$n", - rdLoc(test), strLit) + "if (!($1)) #raiseFieldError($2);$n", + rdLoc(test), genStringLiteralFromData(p.module, strLit, e.info)) proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) = if optFieldCheck in p.options: diff --git a/compiler/ccgliterals.nim b/compiler/ccgliterals.nim new file mode 100644 index 000000000..3011f0a94 --- /dev/null +++ b/compiler/ccgliterals.nim @@ -0,0 +1,81 @@ +# +# +# The Nim Compiler +# (c) Copyright 2018 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This include file contains the logic to produce constant string +## and seq literals. The code here is responsible that +## ``const x = ["a", "b"]`` works without hidden runtime creation code. +## The price is that seqs and strings are not purely a library +## implementation. + +template detectVersion(field, corename) = + if m.g.field == 0: + let core = getCompilerProc(corename) + if core == nil or core.kind != skConst: + m.g.field = 1 + else: + m.g.field = int ast.getInt(core.ast) + result = m.g.field + +proc detectStrVersion(m: BModule): int = + detectVersion(strVersion, "nimStrVersion") + +proc detectSeqVersion(m: BModule): int = + detectVersion(seqVersion, "nimSeqVersion") + +# ----- Version 1: GC'ed strings and seqs -------------------------------- + +proc genStringLiteralDataOnlyV1(m: BModule, s: string): Rope = + discard cgsym(m, "TGenericSeq") + result = getTempName(m) + addf(m.s[cfsData], "STRING_LITERAL($1, $2, $3);$n", + [result, makeCString(s), rope(len(s))]) + +proc genStringLiteralV1(m: BModule; n: PNode): Rope = + if s.isNil: + result = ropecg(m, "((#NimStringDesc*) NIM_NIL)", []) + else: + let id = nodeTableTestOrSet(m.dataCache, n, m.labels) + if id == m.labels: + # string literal not found in the cache: + result = ropecg(m, "((#NimStringDesc*) &$1)", + [genStringLiteralDataOnlyV1(m, n.strVal)]) + else: + result = ropecg(m, "((#NimStringDesc*) &$1$2)", + [m.tmpBase, rope(id)]) + +# ------ Version 2: destructor based strings and seqs ----------------------- + +proc genStringLiteralDataOnlyV2(m: BModule, s: string): Rope = + discard "to implement" + +proc genStringLiteralV2(m: BModule; n: PNode): Rope = + discard "to implement" + +# ------ Version selector --------------------------------------------------- + +proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo): Rope = + case detectStrVersion(m) + of 0, 1: result = genStringLiteralDataOnlyV1(m, s) + of 2: result = genStringLiteralDataOnlyV2(m, s) + else: + localError(info, "cannot determine how to produce code for string literal") + +proc genStringLiteralFromData(m: BModule; data: Rope; info: TLineInfo): Rope = + result = ropecg(m, "((#NimStringDesc*) &$1)", + [data]) + +proc genNilStringLiteral(m: BModule; info: TLineInfo): Rope = + result = ropecg(m, "((#NimStringDesc*) NIM_NIL)", []) + +proc genStringLiteral(m: BModule; n: PNode): Rope = + case detectStrVersion(m) + of 0, 1: result = genStringLiteralV1(m, n) + of 2: result = genStringLiteralV2(m, n) + else: + localError(n.info, "cannot determine how to produce code for string literal") diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index ed44c577d..2a4a10555 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -267,10 +267,6 @@ proc addAbiCheck(m: BModule, t: PType, name: Rope) = if isDefined("checkabi"): addf(m.s[cfsTypeInfo], "NIM_CHECK_SIZE($1, $2);$n", [name, rope(getSize(t))]) -proc getTempName(m: BModule): Rope = - result = m.tmpBase & rope(m.labels) - inc m.labels - proc ccgIntroducedPtr(s: PSym): bool = var pt = skipTypes(s.typ, typedescInst) assert skResult != s.kind @@ -316,8 +312,13 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope = of tyPointer: result = typeNameOrLiteral(m, typ, "void*") of tyString: - discard cgsym(m, "NimStringDesc") - result = typeNameOrLiteral(m, typ, "NimStringDesc*") + case detectStrVersion(m) + of 2: + discard cgsym(m, "string") + result = typeNameOrLiteral(m, typ, "NimStringV2") + else: + discard cgsym(m, "NimStringDesc") + result = typeNameOrLiteral(m, typ, "NimStringDesc*") of tyCString: result = typeNameOrLiteral(m, typ, "NCSTRING") of tyBool: result = typeNameOrLiteral(m, typ, "NIM_BOOL") of tyChar: result = typeNameOrLiteral(m, typ, "NIM_CHAR") diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 01610010b..05f222520 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -238,7 +238,12 @@ proc genProc(m: BModule, prc: PSym) template compileToCpp(m: BModule): untyped = gCmd == cmdCompileToCpp or sfCompileToCpp in m.module.flags -include "ccgtypes.nim" +proc getTempName(m: BModule): Rope = + result = m.tmpBase & rope(m.labels) + inc m.labels + +include ccgliterals +include ccgtypes # ------------------------------ Manager of temporaries ------------------ @@ -551,11 +556,13 @@ proc loadDynamicLib(m: BModule, lib: PLib) = for i in countup(0, high(s)): inc(m.labels) if i > 0: add(loadlib, "||") - appcg(m, loadlib, "($1 = #nimLoadLibrary((#NimStringDesc*) &$2))$n", - [tmp, getStrLit(m, s[i])]) + let n = newStrNode(nkStrLit, s[i]) + n.info = lib.path.info + appcg(m, loadlib, "($1 = #nimLoadLibrary($2))$n", + [tmp, genStringLiteral(m, n)]) appcg(m, m.s[cfsDynLibInit], - "if (!($1)) #nimLoadLibraryError((#NimStringDesc*) &$2);$n", - [loadlib, getStrLit(m, lib.path.strVal)]) + "if (!($1)) #nimLoadLibraryError($2);$n", + [loadlib, genStringLiteral(m, lib.path)]) else: var p = newProc(nil, m) p.options = p.options - {optStackTrace, optEndb} diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index efa346934..f8167acdc 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -70,7 +70,7 @@ type threadVarAccessed*: bool # true if the proc already accessed some threadvar lastLineInfo*: TLineInfo # to avoid generating excessive 'nimln' statements currLineInfo*: TLineInfo # AST codegen will make this superfluous - nestedTryStmts*: seq[tuple[n: PNode, inExcept: bool]] + nestedTryStmts*: seq[tuple[n: PNode, inExcept: bool]] # in how many nested try statements we are # (the vars must be volatile then) # bool is true when are in the except part of a try block @@ -116,6 +116,7 @@ type breakpoints*: Rope # later the breakpoints are inserted into the main proc typeInfoMarker*: TypeCache config*: ConfigRef + strVersion*, seqVersion*: int # version of the string/seq implementation to use TCGen = object of TPassContext # represents a C source file s*: TCFileSections # sections of the C file diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 1295ee18d..78ded578f 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -65,7 +65,7 @@ const wGensym, wInject, wCodegenDecl, wGuard, wGoto, wExportNims, wUsed} constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl, wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject, wExportNims, - wIntDefine, wStrDefine, wUsed} + wIntDefine, wStrDefine, wUsed, wCompilerProc, wCore} letPragmas* = varPragmas procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect, wThread, wRaises, wLocks, wTags, wGcSafe} diff --git a/lib/core/seqs.nim b/lib/core/seqs.nim index c32cf3690..02c192851 100644 --- a/lib/core/seqs.nim +++ b/lib/core/seqs.nim @@ -15,11 +15,11 @@ type len, cap: int data: ptr UncheckedArray[T] +const nimSeqVersion {.core.} = 2 + template frees(s) = dealloc(s.data, s.cap * sizeof(T)) # XXX make code memory safe for overflows in '*' -proc nimSeqLiteral[T](x: openArray[T]): seq[T] {.core.} = - seq[T](len: x.len, cap: x.len, data: x) when defined(nimHasTrace): proc `=trace`[T](s: seq[T]; a: Allocator) = @@ -120,7 +120,7 @@ proc `$`*[T](x: seq[T]): string = result = "@[" var firstElement = true for i in 0.. 0: result.data = alloc0(len+1) -converter toCString(x: string): cstring {.core.} = +converter toCString(x: string): cstring {.core, inline.} = if x.len == 0: cstring"" else: cast[cstring](x.data) proc newStringOfCap*(cap: int): string = -- cgit 1.4.1-2-gfad0 From 8518683dc7f76465b41bd0ccf19f9fab06cd5e32 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 6 Apr 2018 11:56:53 +0200 Subject: the 'deprecated' pragma for modules now supports an error message --- compiler/ast.nim | 2 ++ compiler/importer.nim | 5 ++++- compiler/pragmas.nim | 8 ++++++-- 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'compiler/pragmas.nim') diff --git a/compiler/ast.nim b/compiler/ast.nim index a28a7e7e3..ad4d6fed8 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -847,6 +847,8 @@ type constraint*: PNode # additional constraints like 'lit|result'; also # misused for the codegenDecl pragma in the hope # it won't cause problems + # for skModule the string literal to output for + # deprecated modules. when defined(nimsuggest): allUsages*: seq[TLineInfo] diff --git a/compiler/importer.nim b/compiler/importer.nim index 3d7f62464..f4903e6c4 100644 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -148,7 +148,10 @@ proc myImportModule(c: PContext, n: PNode): PSym = result.info.fileIndex == n.info.fileIndex: localError(n.info, errGenerated, "A module cannot import itself") if sfDeprecated in result.flags: - message(n.info, warnDeprecated, result.name.s) + if result.constraint != nil: + message(n.info, warnDeprecated, result.constraint.strVal & "; " & result.name.s) + else: + message(n.info, warnDeprecated, result.name.s) suggestSym(n.info, result, c.graph.usageSym, false) proc impMod(c: PContext; it: PNode) = diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 78ded578f..d5fed7640 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -620,8 +620,12 @@ proc markCompilerProc(s: PSym) = incl(s.flags, sfUsed) registerCompilerProc(s) -proc deprecatedStmt(c: PContext; pragma: PNode) = - let pragma = pragma[1] +proc deprecatedStmt(c: PContext; outerPragma: PNode) = + let pragma = outerPragma[1] + if pragma.kind in {nkStrLit..nkTripleStrLit}: + incl(c.module.flags, sfDeprecated) + c.module.constraint = getStrLitNode(c, outerPragma) + return if pragma.kind != nkBracket: localError(pragma.info, "list of key:value pairs expected"); return for n in pragma: -- cgit 1.4.1-2-gfad0 From 47335aab4148b2cd5b28cd3012d6d6e0a0c82db7 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 13 Apr 2018 17:06:46 +0200 Subject: introduce nkTupleConstr AST node for unary tuple construction; breaking change --- changelog.md | 4 ++++ compiler/ast.nim | 3 ++- compiler/ccgexprs.nim | 4 ++-- compiler/dfa.nim | 2 +- compiler/evalffi.nim | 6 +++--- compiler/jsgen.nim | 8 ++++---- compiler/parser.nim | 6 ++++++ compiler/pragmas.nim | 4 ++-- compiler/renderer.nim | 8 ++++++++ compiler/sem.nim | 2 +- compiler/semexprs.nim | 20 +++++++++++--------- compiler/semfold.nim | 6 +++--- compiler/semmacrosanity.nim | 2 +- compiler/semmagic.nim | 2 +- compiler/semstmts.nim | 4 ++-- compiler/semtypes.nim | 5 +++-- compiler/transf.nim | 6 +++--- compiler/trees.nim | 2 +- compiler/vm.nim | 18 +++++++++--------- compiler/vmdeps.nim | 2 +- compiler/vmgen.nim | 6 +++--- compiler/vmmarshal.nim | 2 +- compiler/vmops.nim | 4 ++-- compiler/writetracking.nim | 4 ++-- lib/core/macros.nim | 3 ++- tests/tuples/tanontuples.nim | 14 +++++++++++++- 26 files changed, 91 insertions(+), 56 deletions(-) (limited to 'compiler/pragmas.nim') diff --git a/changelog.md b/changelog.md index ce2fc08f3..364047d05 100644 --- a/changelog.md +++ b/changelog.md @@ -5,6 +5,10 @@ - The stdlib module ``future`` has been renamed to ``sugar``. - ``macros.callsite`` is now deprecated. Since the introduction of ``varargs`` parameters this became unnecessary. +- Anonymous tuples with a single element can now be written as ``(1,)`` with a + trailing comma. The underlying AST is ``nnkTupleConst(newLit 1)`` for this + example. ``nnkTupleConstr`` is a new node kind your macros need to be able + to deal with! #### Breaking changes in the standard library diff --git a/compiler/ast.nim b/compiler/ast.nim index aa7250513..da7e828f2 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -221,7 +221,8 @@ type nkGotoState, # used for the state machine (for iterators) nkState, # give a label to a code section (for iterators) nkBreakState, # special break statement for easier code generation - nkFuncDef # a func + nkFuncDef, # a func + nkTupleConstr # a tuple constructor TNodeKinds* = set[TNodeKind] diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 5888f6430..7e3c2632a 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2226,7 +2226,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = genSeqConstr(p, n, d) else: genArrayConstr(p, n, d) - of nkPar: + of nkPar, nkTupleConstr: if isDeepConstExpr(n) and n.len != 0: exprComplexConst(p, n, d) else: @@ -2458,7 +2458,7 @@ proc genConstExpr(p: BProc, n: PNode): Rope = var cs: TBitSet toBitSet(n, cs) result = genRawSetData(cs, int(getSize(n.typ))) - of nkBracket, nkPar, nkClosure: + of nkBracket, nkPar, nkTupleConstr, nkClosure: var t = skipTypes(n.typ, abstractInst) if t.kind == tySequence: result = genConstSeq(p, n, n.typ) diff --git a/compiler/dfa.nim b/compiler/dfa.nim index b648995f4..bc9d13870 100644 --- a/compiler/dfa.nim +++ b/compiler/dfa.nim @@ -323,7 +323,7 @@ proc gen(c: var Con; n: PNode) = of nkBreakStmt: genBreak(c, n) of nkTryStmt: genTry(c, n) of nkStmtList, nkStmtListExpr, nkChckRangeF, nkChckRange64, nkChckRange, - nkBracket, nkCurly, nkPar, nkClosure, nkObjConstr: + nkBracket, nkCurly, nkPar, nkTupleConstr, nkClosure, nkObjConstr: for x in n: gen(c, x) of nkPragmaBlock: gen(c, n.lastSon) of nkDiscardStmt: gen(c, n.sons[0]) diff --git a/compiler/evalffi.nim b/compiler/evalffi.nim index 5bf8f358a..0e3d0609d 100644 --- a/compiler/evalffi.nim +++ b/compiler/evalffi.nim @@ -151,7 +151,7 @@ proc getField(n: PNode; position: int): PSym = else: discard proc packObject(x: PNode, typ: PType, res: pointer) = - internalAssert x.kind in {nkObjConstr, nkPar} + internalAssert x.kind in {nkObjConstr, nkPar, nkTupleConstr} # compute the field's offsets: discard typ.getSize for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1): @@ -260,14 +260,14 @@ proc unpackObject(x: pointer, typ: PType, n: PNode): PNode = # iterate over any actual field of 'n' ... if n is nil we need to create # the nkPar node: if n.isNil: - result = newNode(nkPar) + result = newNode(nkTupleConstr) result.typ = typ if typ.n.isNil: internalError("cannot unpack unnamed tuple") unpackObjectAdd(x, typ.n, result) else: result = n - if result.kind notin {nkObjConstr, nkPar}: + if result.kind notin {nkObjConstr, nkPar, nkTupleConstr}: globalError(n.info, "cannot map value from FFI") if typ.n.isNil: globalError(n.info, "cannot unpack unnamed tuple") diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index dc74fa933..357708bb9 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -307,7 +307,7 @@ proc useMagic(p: PProc, name: string) = proc isSimpleExpr(p: PProc; n: PNode): bool = # calls all the way down --> can stay expression based - if n.kind in nkCallKinds+{nkBracketExpr, nkDotExpr, nkPar} or + if n.kind in nkCallKinds+{nkBracketExpr, nkDotExpr, nkPar, nkTupleConstr} or (p.target == targetJS and n.kind in {nkObjConstr, nkBracket, nkCurly}): for c in n: if not p.isSimpleExpr(c): return false @@ -894,7 +894,7 @@ proc countJsParams(typ: PType): int = const nodeKindsNeedNoCopy = {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, - nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkObjConstr, nkStringToCString, + nkFloatLit..nkFloat64Lit, nkCurly, nkPar, nkTupleConstr, nkObjConstr, nkStringToCString, nkCStringToString, nkCall, nkPrefix, nkPostfix, nkInfix, nkCommand, nkHiddenCallConv, nkCallStrLit} @@ -1714,7 +1714,7 @@ proc genToArray(p: PProc; n: PNode; r: var TCompRes) = if x.kind == nkBracket: for i in countup(0, x.len - 1): let it = x[i] - if it.kind == nkPar and it.len == 2: + if it.kind in {nkPar, nkTupleConstr} and it.len == 2: if i > 0: r.res.add(", ") gen(p, it[0], a) gen(p, it[1], b) @@ -2309,7 +2309,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) = of nkClosure: gen(p, n[0], r) of nkCurly: genSetConstr(p, n, r) of nkBracket: genArrayConstr(p, n, r) - of nkPar: genTupleConstr(p, n, r) + of nkPar, nkTupleConstr: genTupleConstr(p, n, r) of nkObjConstr: genObjConstr(p, n, r) of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, r) of nkAddr, nkHiddenAddr: diff --git a/compiler/parser.nim b/compiler/parser.nim index c14330ec2..c8edd5136 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -399,6 +399,9 @@ proc exprColonEqExprListAux(p: var TParser, endTok: TTokType, result: PNode) = addSon(result, a) if p.tok.tokType != tkComma: break getTok(p) + # (1,) produces a tuple expression + if endTok == tkParRi and p.tok.tokType == tkParRi: + result.kind = nkTupleConstr skipComment(p, a) optPar(p) eat(p, endTok) @@ -566,6 +569,9 @@ proc parsePar(p: var TParser): PNode = if p.tok.tokType == tkComma: getTok(p) skipComment(p, a) + # (1,) produces a tuple expression: + if p.tok.tokType == tkParRi: + result.kind = nkTupleConstr # progress guaranteed while p.tok.tokType != tkParRi and p.tok.tokType != tkEof: var a = exprColonEqExpr(p) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index d5fed7640..bb7801f6f 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -423,7 +423,7 @@ proc processCompile(c: PContext, n: PNode) = result = "" let it = if n.kind in nkPragmaCallKinds and n.len == 2: n.sons[1] else: n - if it.kind == nkPar and it.len == 2: + if it.kind in {nkPar, nkTupleConstr} and it.len == 2: let s = getStrLit(c, it, 0) let dest = getStrLit(c, it, 1) var found = parentDir(n.info.toFullPath) / s @@ -530,7 +530,7 @@ proc pragmaLine(c: PContext, n: PNode) = if n.kind in nkPragmaCallKinds and n.len == 2: n.sons[1] = c.semConstExpr(c, n.sons[1]) let a = n.sons[1] - if a.kind == nkPar: + if a.kind in {nkPar, nkTupleConstr}: # unpack the tuple var x = a.sons[0] var y = a.sons[1] diff --git a/compiler/renderer.nim b/compiler/renderer.nim index 0b1b0479f..7d513afb1 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -437,6 +437,9 @@ proc lsub(g: TSrcGen; n: PNode): int = of nkCommand: result = lsub(g, n.sons[0]) + lcomma(g, n, 1) + 1 of nkExprEqExpr, nkAsgn, nkFastAsgn: result = lsons(g, n) + 3 of nkPar, nkCurly, nkBracket, nkClosure: result = lcomma(g, n) + 2 + of nkTupleConstr: + # assume the trailing comma: + result = lcomma(g, n) + 3 of nkArgList: result = lcomma(g, n) of nkTableConstr: result = if n.len > 0: lcomma(g, n) + 2 else: len("{:}") @@ -1007,6 +1010,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) = put(g, tkParLe, "(") gcomma(g, n, c) put(g, tkParRi, ")") + of nkTupleConstr: + put(g, tkParLe, "(") + gcomma(g, n, c) + if n.len == 1: put(g, tkComma, ",") + put(g, tkParRi, ")") of nkCurly: put(g, tkCurlyLe, "{") gcomma(g, n, c) diff --git a/compiler/sem.nim b/compiler/sem.nim index 937f1637a..4fef1bc60 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -85,7 +85,7 @@ proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode = result.typ = formal else: let x = result.skipConv - if x.kind == nkPar and formal.kind != tyExpr: + if x.kind in {nkPar, nkTupleConstr} and formal.kind != tyExpr: changeType(x, formal, check=true) else: result = skipHiddenSubConv(result) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index a523bfc9e..4256e0aa6 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -215,7 +215,7 @@ proc semConv(c: PContext, n: PNode): PNode = # handle SomeProcType(SomeGenericProc) if op.kind == nkSym and op.sym.isGenericRoutine: result.sons[1] = fitNode(c, result.typ, result.sons[1], result.info) - elif op.kind == nkPar and targetType.kind == tyTuple: + elif op.kind in {nkPar, nkTupleConstr} and targetType.kind == tyTuple: op = fitNode(c, targetType, op, result.info) of convNotNeedeed: message(n.info, hintConvFromXtoItselfNotNeeded, result.typ.typeToString) @@ -364,7 +364,7 @@ proc changeType(n: PNode, newType: PType, check: bool) = of nkCurly, nkBracket: for i in countup(0, sonsLen(n) - 1): changeType(n.sons[i], elemType(newType), check) - of nkPar: + of nkPar, nkTupleConstr: let tup = newType.skipTypes({tyGenericInst, tyAlias, tySink}) if tup.kind != tyTuple: if tup.kind == tyObject: return @@ -1402,7 +1402,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode = result = buildOverloadedSubscripts(n.sons[0], getIdent"{}=") add(result, n[1]) return semExprNoType(c, result) - of nkPar: + of nkPar, nkTupleConstr: if a.len >= 2: # unfortunately we need to rewrite ``(x, y) = foo()`` already here so # that overloading of the assignment operator still works. Usually we @@ -1521,10 +1521,10 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) = var e = skipTypes(t.sons[i], {tyGenericInst, tyAlias, tySink}) if e.kind in {tyVar, tyLent}: if e.kind == tyVar: e.flags.incl tfVarIsPtr # bugfix for #4048, #4910, #6892 - if n.sons[0].kind == nkPar: + if n.sons[0].kind in {nkPar, nkTupleConstr}: n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i], e.kind == tyLent) elif n.sons[0].kind in {nkHiddenStdConv, nkHiddenSubConv} and - n.sons[0].sons[1].kind == nkPar: + n.sons[0].sons[1].kind in {nkPar, nkTupleConstr}: var a = n.sons[0].sons[1] a.sons[i] = takeImplicitAddr(c, a.sons[i], false) else: @@ -2047,12 +2047,12 @@ proc semTableConstr(c: PContext, n: PNode): PNode = var x = n.sons[i] if x.kind == nkExprColonExpr and sonsLen(x) == 2: for j in countup(lastKey, i-1): - var pair = newNodeI(nkPar, x.info) + var pair = newNodeI(nkTupleConstr, x.info) pair.add(n.sons[j]) pair.add(x[1]) result.add(pair) - var pair = newNodeI(nkPar, x.info) + var pair = newNodeI(nkTupleConstr, x.info) pair.add(x[0]) pair.add(x[1]) result.add(pair) @@ -2072,6 +2072,7 @@ proc checkPar(n: PNode): TParKind = result = paTuplePositions # () elif length == 1: if n.sons[0].kind == nkExprColonExpr: result = paTupleFields + elif n.kind == nkTupleConstr: result = paTuplePositions else: result = paSingle # (expr) else: if n.sons[0].kind == nkExprColonExpr: result = paTupleFields @@ -2088,7 +2089,7 @@ proc checkPar(n: PNode): TParKind = return paNone proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = - result = newNodeI(nkPar, n.info) + result = newNodeI(nkTupleConstr, n.info) var typ = newTypeS(tyTuple, c) typ.n = newNodeI(nkRecList, n.info) # nkIdentDefs var ids = initIntSet() @@ -2113,6 +2114,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = result = n # we don't modify n, but compute the type: + result.kind = nkTupleConstr var typ = newTypeS(tyTuple, c) # leave typ.n nil! for i in countup(0, sonsLen(n) - 1): n.sons[i] = semExprWithType(c, n.sons[i], flags*{efAllowDestructor}) @@ -2344,7 +2346,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = invalidPragma(n) result = semExpr(c, n[0], flags) - of nkPar: + of nkPar, nkTupleConstr: case checkPar(n) of paNone: result = errorNode(c, n) of paTuplePositions: diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 62bab4edb..096fc19e0 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -427,7 +427,7 @@ proc foldArrayAccess(m: PSym, n: PNode): PNode = var idx = getOrdValue(y) case x.kind - of nkPar: + of nkPar, nkTupleConstr: if idx >= 0 and idx < sonsLen(x): result = x.sons[int(idx)] if result.kind == nkExprColonExpr: result = result.sons[1] @@ -450,7 +450,7 @@ proc foldArrayAccess(m: PSym, n: PNode): PNode = proc foldFieldAccess(m: PSym, n: PNode): PNode = # a real field access; proc calls have already been transformed var x = getConstExpr(m, n.sons[0]) - if x == nil or x.kind notin {nkObjConstr, nkPar}: return + if x == nil or x.kind notin {nkObjConstr, nkPar, nkTupleConstr}: return var field = n.sons[1].sym for i in countup(ord(x.kind == nkObjConstr), sonsLen(x) - 1): @@ -624,7 +624,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode = # if a == nil: return nil # result.sons[i].sons[1] = a # incl(result.flags, nfAllConst) - of nkPar: + of nkPar, nkTupleConstr: # tuple constructor result = copyTree(n) if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr): diff --git a/compiler/semmacrosanity.nim b/compiler/semmacrosanity.nim index fe9bb6c8d..f6df67441 100644 --- a/compiler/semmacrosanity.nim +++ b/compiler/semmacrosanity.nim @@ -50,7 +50,7 @@ proc annotateType*(n: PNode, t: PType) = else: internalAssert(n.sons[i].kind == nkExprColonExpr) annotateType(n.sons[i].sons[1], field.typ) - of nkPar: + of nkPar, nkTupleConstr: if x.kind == tyTuple: n.typ = t for i in 0 ..< n.len: diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index 9031e4640..3f0df0065 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -73,7 +73,7 @@ proc expectIntLit(c: PContext, n: PNode): int = else: localError(n.info, errIntLiteralExpected) proc semInstantiationInfo(c: PContext, n: PNode): PNode = - result = newNodeIT(nkPar, n.info, n.typ) + result = newNodeIT(nkTupleConstr, n.info, n.typ) let idx = expectIntLit(c, n.sons[1]) let useFullPaths = expectIntLit(c, n.sons[2]) let info = getInfoContext(idx) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index c53ff9803..3de26344c 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -552,7 +552,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator b.sons[length-1] = def addToVarSection(c, result, n, b) - elif tup.kind == tyTuple and def.kind == nkPar and + elif tup.kind == tyTuple and def.kind in {nkPar, nkTupleConstr} and a.kind == nkIdentDefs and a.len > 3: message(a.info, warnEachIdentIsTuple) @@ -592,7 +592,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = addSon(b, copyTree(def)) addToVarSection(c, result, n, b) else: - if def.kind == nkPar: v.ast = def[j] + if def.kind in {nkPar, nkTupleConstr}: v.ast = def[j] setVarType(v, tup.sons[j]) b.sons[j] = newSymNode(v) checkNilable(v) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index a23ee01e1..1fc263617 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -392,8 +392,8 @@ proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType = if sonsLen(n) == 0: localError(n.info, errTypeExpected) result = newOrPrevType(tyTuple, prev, c) - for i in countup(0, sonsLen(n) - 1): - addSonSkipIntLit(result, semTypeNode(c, n.sons[i], nil)) + for it in n: + addSonSkipIntLit(result, semTypeNode(c, it, nil)) proc semTuple(c: PContext, n: PNode, prev: PType): PType = var typ: PType @@ -1341,6 +1341,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev) else: result = semAnonTuple(c, n, prev) + of nkTupleConstr: result = semAnonTuple(c, n, prev) of nkCallKinds: let x = n[0] let ident = case x.kind diff --git a/compiler/transf.nim b/compiler/transf.nim index e6dc69b38..f30f8583a 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -334,7 +334,7 @@ proc transformYield(c: PTransf, n: PNode): PTransNode = if skipTypes(e.typ, {tyGenericInst, tyAlias, tySink}).kind == tyTuple and c.transCon.forStmt.len != 3: e = skipConv(e) - if e.kind == nkPar: + if e.kind in {nkPar, nkTupleConstr}: for i in countup(0, sonsLen(e) - 1): var v = e.sons[i] if v.kind == nkExprColonExpr: v = v.sons[1] @@ -500,7 +500,7 @@ proc putArgInto(arg: PNode, formal: PType): TPutArgInto = case arg.kind of nkEmpty..nkNilLit: result = paDirectMapping - of nkPar, nkCurly, nkBracket: + of nkPar, nkTupleConstr, nkCurly, nkBracket: result = paFastAsgn for i in countup(0, sonsLen(arg) - 1): if putArgInto(arg.sons[i], formal) != paDirectMapping: return @@ -745,7 +745,7 @@ proc transformExceptBranch(c: PTransf, n: PNode): PTransNode = proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} = # symbols that expand to a complex constant (array, etc.) should not be # inlined, unless it's the empty array: - result = orig.kind == nkSym and cnst.kind in {nkCurly, nkPar, nkBracket} and + result = orig.kind == nkSym and cnst.kind in {nkCurly, nkPar, nkTupleConstr, nkBracket} and cnst.len != 0 proc commonOptimizations*(c: PSym, n: PNode): PNode = diff --git a/compiler/trees.nim b/compiler/trees.nim index f69108942..fb523de9d 100644 --- a/compiler/trees.nim +++ b/compiler/trees.nim @@ -97,7 +97,7 @@ proc isDeepConstExpr*(n: PNode): bool = result = true of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv: result = isDeepConstExpr(n.sons[1]) - of nkCurly, nkBracket, nkPar, nkObjConstr, nkClosure, nkRange: + of nkCurly, nkBracket, nkPar, nkTupleConstr, nkObjConstr, nkClosure, nkRange: for i in ord(n.kind == nkObjConstr) ..< n.len: if not isDeepConstExpr(n.sons[i]): return false if n.typ.isNil: result = true diff --git a/compiler/vm.nim b/compiler/vm.nim index 33c17eff4..7e2a171a2 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -418,14 +418,14 @@ proc setLenSeq(c: PCtx; node: PNode; newLen: int; info: TLineInfo) = let typ = node.typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc}) let typeEntry = typ.sons[0].skipTypes(abstractInst+{tyRange}-{tyTypeDesc}) let typeKind = case typeEntry.kind - of tyUInt..tyUInt64: nkUIntLit - of tyRange, tyEnum, tyBool, tyChar, tyInt..tyInt64: nkIntLit - of tyFloat..tyFloat128: nkFloatLit - of tyString: nkStrLit - of tyObject: nkObjConstr - of tySequence: nkNilLit - of tyProc, tyTuple: nkPar - else: nkEmpty + of tyUInt..tyUInt64: nkUIntLit + of tyRange, tyEnum, tyBool, tyChar, tyInt..tyInt64: nkIntLit + of tyFloat..tyFloat128: nkFloatLit + of tyString: nkStrLit + of tyObject: nkObjConstr + of tySequence: nkNilLit + of tyProc, tyTuple: nkTupleConstr + else: nkEmpty let oldLen = node.len setLen(node.sons, newLen) @@ -939,7 +939,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let rb = instr.regB let rc = instr.regC let bb = regs[rb].node - let isClosure = bb.kind == nkPar + let isClosure = bb.kind == nkTupleConstr let prc = if not isClosure: bb.sym else: bb.sons[0].sym if prc.offset < -1: # it's a callback: diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index bb6c47324..071cc7706 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -186,7 +186,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo; if inst: # only named tuples have a node, unnamed tuples don't if t.n.isNil: - result = newNodeX(nkPar) + result = newNodeX(nkTupleConstr) for subType in t.sons: result.add mapTypeToAst(subType, info) else: diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index a8ecfd4ae..c3eaf8946 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1560,7 +1560,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode = if t.callConv != ccClosure: result = newNodeIT(nkNilLit, info, t) else: - result = newNodeIT(nkPar, info, t) + result = newNodeIT(nkTupleConstr, info, t) result.add(newNodeIT(nkNilLit, info, t)) result.add(newNodeIT(nkNilLit, info, t)) of tyObject: @@ -1577,7 +1577,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode = for i in countup(0, int(lengthOrd(t)) - 1): addSon(result, getNullValue(elemType(t), info)) of tyTuple: - result = newNodeIT(nkPar, info, t) + result = newNodeIT(nkTupleConstr, info, t) for i in countup(0, sonsLen(t) - 1): addSon(result, getNullValue(t.sons[i], info)) of tySet: @@ -1884,7 +1884,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = of nkBracket: genArrayConstr(c, n, dest) of nkCurly: genSetConstr(c, n, dest) of nkObjConstr: genObjConstr(c, n, dest) - of nkPar, nkClosure: genTupleConstr(c, n, dest) + of nkPar, nkClosure, nkTupleConstr: genTupleConstr(c, n, dest) of nkCast: if allowCast in c.features: genConv(c, n, n.sons[1], dest, opcCast) diff --git a/compiler/vmmarshal.nim b/compiler/vmmarshal.nim index 5f725994e..d76909443 100644 --- a/compiler/vmmarshal.nim +++ b/compiler/vmmarshal.nim @@ -190,7 +190,7 @@ proc loadAny(p: var JsonParser, t: PType, of tyTuple: if p.kind != jsonObjectStart: raiseParseErr(p, "'{' expected for an object") next(p) - result = newNode(nkPar) + result = newNode(nkTupleConstr) var i = 0 while p.kind != jsonObjectEnd and p.kind != jsonEof: if p.kind != jsonString: diff --git a/compiler/vmops.nim b/compiler/vmops.nim index f7debe2df..7f8bf06c1 100644 --- a/compiler/vmops.nim +++ b/compiler/vmops.nim @@ -74,13 +74,13 @@ proc getCurrentExceptionMsgWrapper(a: VmArgs) {.nimcall.} = proc staticWalkDirImpl(path: string, relative: bool): PNode = result = newNode(nkBracket) for k, f in walkDir(path, relative): - result.add newTree(nkPar, newIntNode(nkIntLit, k.ord), + result.add newTree(nkTupleConstr, newIntNode(nkIntLit, k.ord), newStrNode(nkStrLit, f)) proc gorgeExWrapper(a: VmArgs) {.nimcall.} = let (s, e) = opGorge(getString(a, 0), getString(a, 1), getString(a, 2), a.currentLineInfo) - setResult a, newTree(nkPar, newStrNode(nkStrLit, s), newIntNode(nkIntLit, e)) + setResult a, newTree(nkTupleConstr, newStrNode(nkStrLit, s), newIntNode(nkIntLit, e)) proc getProjectPathWrapper(a: VmArgs) {.nimcall.} = setResult a, gProjectPath diff --git a/compiler/writetracking.nim b/compiler/writetracking.nim index 577db613d..e03d6fb59 100644 --- a/compiler/writetracking.nim +++ b/compiler/writetracking.nim @@ -120,7 +120,7 @@ proc returnsNewExpr*(n: PNode): NewLocation = nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkOfBranch, nkElifBranch, nkElse, nkExceptBranch, nkFinally, nkCast: result = returnsNewExpr(n.lastSon) - of nkCurly, nkBracket, nkPar, nkObjConstr, nkClosure, + of nkCurly, nkBracket, nkPar, nkTupleConstr, nkObjConstr, nkClosure, nkIfExpr, nkIfStmt, nkWhenStmt, nkCaseStmt, nkTryStmt: result = newLit for i in ord(n.kind == nkObjConstr) ..< n.len: @@ -179,7 +179,7 @@ proc deps(w: var W; n: PNode) = for child in n: let last = lastSon(child) if last.kind == nkEmpty: continue - if child.kind == nkVarTuple and last.kind == nkPar: + if child.kind == nkVarTuple and last.kind in {nkPar, nkTupleConstr}: internalAssert child.len-2 == last.len for i in 0 .. child.len-3: deps(w, child.sons[i], last.sons[i], {}) diff --git a/lib/core/macros.nim b/lib/core/macros.nim index 3bdd29b0a..a4c819a34 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -82,7 +82,8 @@ type nnkGotoState, nnkState, nnkBreakState, - nnkFuncDef + nnkFuncDef, + nnkTupleConstr NimNodeKinds* = set[NimNodeKind] NimTypeKind* = enum # some types are no longer used, see ast.nim diff --git a/tests/tuples/tanontuples.nim b/tests/tuples/tanontuples.nim index 49803e5ac..f514670d3 100644 --- a/tests/tuples/tanontuples.nim +++ b/tests/tuples/tanontuples.nim @@ -1,7 +1,10 @@ discard """ - output: '''61, 125''' + output: '''61, 125 +(Field0: 0) (Field0: 13)''' """ +import macros + proc `^` (a, b: int): int = result = 1 for i in 1..b: result = result * a @@ -12,3 +15,12 @@ var n = (56, 3) m = (n[0] + m[1], m[1] ^ n[1]) echo m[0], ", ", m[1] + +# also test we can produce unary anon tuples in a macro: +macro mm(): untyped = + result = newTree(nnkTupleConstr, newLit(13)) + +proc nowTuple(): (int,) = + result = (0,) + +echo nowTuple(), " ", mm() -- cgit 1.4.1-2-gfad0 From 33b69f0ed0272a4792322d9a0fbaffd5bef2f6e9 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 21 Apr 2018 08:13:37 +0200 Subject: refactoring: make FileIndex a distinct type; make line information an uint16; fixes #7654 --- compiler/ast.nim | 10 ++-- compiler/ccgexprs.nim | 2 +- compiler/cgen.nim | 12 ++--- compiler/commands.nim | 2 +- compiler/docgen.nim | 10 ++-- compiler/filter_tmpl.nim | 6 +-- compiler/jsgen.nim | 2 +- compiler/lexer.nim | 18 +++---- compiler/main.nim | 4 +- compiler/modulegraphs.nim | 40 ++++++++------- compiler/modulepaths.nim | 2 +- compiler/modules.nim | 20 ++++---- compiler/msgs.nim | 107 ++++++++++++++++++++------------------- compiler/nimfix/pretty.nim | 10 ++-- compiler/nimfix/prettybase.nim | 16 +++--- compiler/parampatterns.nim | 3 +- compiler/parser.nim | 2 +- compiler/passes.nim | 24 ++------- compiler/pbraces.nim | 2 +- compiler/pragmas.nim | 2 +- compiler/reorder.nim | 20 ++++---- compiler/rod.nim | 112 ++--------------------------------------- compiler/rodread.nim | 47 +++++++++-------- compiler/rodwrite.nim | 10 ++-- compiler/semdata.nim | 2 +- compiler/semstmts.nim | 8 +-- compiler/suggest.nim | 4 +- compiler/syntaxes.nim | 4 +- compiler/vm.nim | 6 +-- 29 files changed, 196 insertions(+), 311 deletions(-) (limited to 'compiler/pragmas.nim') diff --git a/compiler/ast.nim b/compiler/ast.nim index da7e828f2..4a0a9a20b 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1042,9 +1042,9 @@ proc newNode*(kind: TNodeKind): PNode = new(result) result.kind = kind #result.info = UnknownLineInfo() inlined: - result.info.fileIndex = int32(-1) + result.info.fileIndex = InvalidFileIdx result.info.col = int16(-1) - result.info.line = int16(-1) + result.info.line = uint16(0) when defined(useNodeIds): result.id = gNodeId if result.id == nodeIdToDebug: @@ -1116,13 +1116,13 @@ proc linkTo*(s: PSym, t: PType): PSym {.discardable.} = s.typ = t result = s -template fileIdx*(c: PSym): int32 = +template fileIdx*(c: PSym): FileIndex = # XXX: this should be used only on module symbols - c.position.int32 + c.position.FileIndex template filename*(c: PSym): string = # XXX: this should be used only on module symbols - c.position.int32.toFilename + c.position.FileIndex.toFilename proc appendToModule*(m: PSym, n: PNode) = ## The compiler will use this internally to add nodes that will be diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 7e3c2632a..461a86298 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2023,7 +2023,7 @@ template genStmtListExprImpl(exprOrStmt) {.dirty.} = let theMacro = it[0].sym add p.s(cpsStmts), initFrameNoDebug(p, frameName, makeCString theMacro.name.s, - theMacro.info.quotedFilename, it.info.line) + theMacro.info.quotedFilename, it.info.line.int) else: genStmts(p, it) if n.len > 0: exprOrStmt diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 4d3cabd3a..9e1f9349f 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -223,7 +223,7 @@ proc genLineDir(p: BProc, t: PNode) = line.rope, makeCString(toFilename(tt.info))) elif ({optLineTrace, optStackTrace} * p.options == {optLineTrace, optStackTrace}) and - (p.prc == nil or sfPure notin p.prc.flags) and tt.info.fileIndex >= 0: + (p.prc == nil or sfPure notin p.prc.flags) and tt.info.fileIndex != InvalidFileIDX: if freshLineInfo(p, tt.info): linefmt(p, cpsStmts, "nimln_($1, $2);$n", line.rope, tt.info.quotedFilename) @@ -678,7 +678,7 @@ proc generateHeaders(m: BModule) = proc openNamespaceNim(): Rope = result.add("namespace Nim {" & tnl) - + proc closeNamespaceNim(): Rope = result.add("}" & tnl) @@ -1090,7 +1090,7 @@ proc genMainProc(m: BModule) = appcg(m, m.s[cfsProcs], nimMain, [m.g.mainModInit, initStackBottomCall, rope(m.labels)]) if optNoMain notin gGlobalOptions: - if useNimNamespace: + if useNimNamespace: m.s[cfsProcs].add closeNamespaceNim() & "using namespace Nim;" & tnl appcg(m, m.s[cfsProcs], otherMain, []) @@ -1202,7 +1202,7 @@ proc genModule(m: BModule, cfile: Cfile): Rope = add(result, genSectionStart(i)) add(result, m.s[i]) add(result, genSectionEnd(i)) - if useNimNamespace and i == cfsHeaders: result.add openNamespaceNim() + if useNimNamespace and i == cfsHeaders: result.add openNamespaceNim() add(result, m.s[cfsInitProc]) if useNimNamespace: result.add closeNamespaceNim() @@ -1301,7 +1301,7 @@ proc resetCgenModules*(g: BModuleList) = for m in cgenModules(g): resetModule(m) proc rawNewModule(g: BModuleList; module: PSym): BModule = - result = rawNewModule(g, module, module.position.int32.toFullPath) + result = rawNewModule(g, module, module.position.FileIndex.toFullPath) proc newModule(g: BModuleList; module: PSym): BModule = # we should create only one cgen module for each module sym @@ -1311,7 +1311,7 @@ proc newModule(g: BModuleList; module: PSym): BModule = if (optDeadCodeElim in gGlobalOptions): if (sfDeadCodeElim in module.flags): - internalError("added pending module twice: " & module.filename) + internalError("added pending module twice: " & toFilename(FileIndex module.position)) template injectG(config) {.dirty.} = if graph.backend == nil: diff --git a/compiler/commands.nim b/compiler/commands.nim index ec58706f3..e1dc1aacf 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -319,7 +319,7 @@ proc trackDirty(arg: string, info: TLineInfo) = localError(info, errInvalidNumber, a[2]) let dirtyOriginalIdx = a[1].fileInfoIdx - if dirtyOriginalIdx >= 0: + if dirtyOriginalIdx.int32 >= 0: msgs.setDirtyFile(dirtyOriginalIdx, a[0]) gTrackPos = newLineInfo(dirtyOriginalIdx, line, column) diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 74fb305ac..6f3dcde8b 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -544,7 +544,7 @@ proc genJsonItem(d: PDoc, n, nameNode: PNode, k: TSymKind): JsonNode = initTokRender(r, n, {renderNoBody, renderNoComments, renderDocComments}) - result = %{ "name": %name, "type": %($k), "line": %n.info.line, + result = %{ "name": %name, "type": %($k), "line": %n.info.line.int, "col": %n.info.col} if comm != nil and comm != "": result["description"] = %comm @@ -618,7 +618,7 @@ proc generateJson*(d: PDoc, n: PNode) = of nkCommentStmt: if n.comment != nil and startsWith(n.comment, "##"): let stripped = n.comment.substr(2).strip - d.add %{ "comment": %stripped, "line": %n.info.line, + d.add %{ "comment": %stripped, "line": %n.info.line.int, "col": %n.info.col } of nkProcDef: when useEffectSystem: documentRaises(n) @@ -790,7 +790,7 @@ proc writeOutputJson*(d: PDoc, filename, outExt: string, discard "fixme: error report" proc commandDoc*() = - var ast = parseFile(gProjectMainIdx, newIdentCache()) + var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache()) if ast == nil: return var d = newDocumentor(gProjectFull, options.gConfigVars) d.hasToc = true @@ -840,7 +840,7 @@ proc commandRst2TeX*() = commandRstAux(gProjectFull, TexExt) proc commandJson*() = - var ast = parseFile(gProjectMainIdx, newIdentCache()) + var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache()) if ast == nil: return var d = newDocumentor(gProjectFull, options.gConfigVars) d.hasToc = true @@ -855,7 +855,7 @@ proc commandJson*() = writeRope(content, getOutFile(gProjectFull, JsonExt), useWarning = false) proc commandTags*() = - var ast = parseFile(gProjectMainIdx, newIdentCache()) + var ast = parseFile(gProjectMainIdx.FileIndex, newIdentCache()) if ast == nil: return var d = newDocumentor(gProjectFull, options.gConfigVars) d.hasToc = true diff --git a/compiler/filter_tmpl.nim b/compiler/filter_tmpl.nim index ca9a3a801..a1ba9113c 100644 --- a/compiler/filter_tmpl.nim +++ b/compiler/filter_tmpl.nim @@ -35,7 +35,7 @@ const proc newLine(p: var TTmplParser) = llStreamWrite(p.outp, repeat(')', p.emitPar)) p.emitPar = 0 - if p.info.line > int16(1): llStreamWrite(p.outp, "\n") + if p.info.line > uint16(1): llStreamWrite(p.outp, "\n") if p.pendingExprLine: llStreamWrite(p.outp, spaces(2)) p.pendingExprLine = false @@ -212,9 +212,9 @@ proc filterTmpl*(stdin: PLLStream, filename: string, call: PNode): PLLStream = p.x = newStringOfCap(120) # do not process the first line which contains the directive: if llStreamReadLine(p.inp, p.x): - p.info.line = p.info.line + int16(1) + p.info.line = p.info.line + 1'u16 while llStreamReadLine(p.inp, p.x): - p.info.line = p.info.line + int16(1) + p.info.line = p.info.line + 1'u16 parseLine(p) newLine(p) result = p.outp diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 475508946..2ae3426ab 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -2261,7 +2261,7 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode = var m = BModule(b) if sfMainModule in m.module.flags: let ext = "js" - let f = if globals.classes.len == 0: m.module.filename + let f = if globals.classes.len == 0: toFilename(FileIndex m.module.position) else: "nimsystem" let code = wholeCode(graph, m) let outfile = diff --git a/compiler/lexer.nim b/compiler/lexer.nim index a4a2615bd..0b1090bb1 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -133,7 +133,7 @@ type TErrorHandler* = proc (info: TLineInfo; msg: TMsgKind; arg: string) TLexer* = object of TBaseLexer - fileIdx*: int32 + fileIdx*: FileIndex indentAhead*: int # if > 0 an indendation has already been read # this is needed because scanning comments # needs so much look-ahead @@ -222,7 +222,7 @@ proc fillToken(L: var TToken) = L.commentOffsetA = 0 L.commentOffsetB = 0 -proc openLexer*(lex: var TLexer, fileIdx: int32, inputstream: PLLStream; +proc openLexer*(lex: var TLexer, fileIdx: FileIndex, inputstream: PLLStream; cache: IdentCache) = openBaseLexer(lex, inputstream) lex.fileIdx = fileidx @@ -274,7 +274,7 @@ template tokenEnd(tok, pos) {.dirty.} = when defined(nimsuggest): let colB = getColNumber(L, pos)+1 if L.fileIdx == gTrackPos.fileIndex and gTrackPos.col in colA..colB and - L.lineNumber == gTrackPos.line and gIdeCmd in {ideSug, ideCon}: + L.lineNumber == gTrackPos.line.int and gIdeCmd in {ideSug, ideCon}: L.cursor = CursorPosition.InToken gTrackPos.col = colA.int16 colA = 0 @@ -285,9 +285,9 @@ template tokenEndIgnore(tok, pos) = when defined(nimsuggest): let colB = getColNumber(L, pos) if L.fileIdx == gTrackPos.fileIndex and gTrackPos.col in colA..colB and - L.lineNumber == gTrackPos.line and gIdeCmd in {ideSug, ideCon}: + L.lineNumber == gTrackPos.line.int and gIdeCmd in {ideSug, ideCon}: gTrackPos.fileIndex = trackPosInvalidFileIdx - gTrackPos.line = -1 + gTrackPos.line = 0'u16 colA = 0 when defined(nimpretty): tok.offsetB = L.offsetBase + pos @@ -299,7 +299,7 @@ template tokenEndPrevious(tok, pos) = # the cursor in a string literal or comment: let colB = getColNumber(L, pos) if L.fileIdx == gTrackPos.fileIndex and gTrackPos.col in colA..colB and - L.lineNumber == gTrackPos.line and gIdeCmd in {ideSug, ideCon}: + L.lineNumber == gTrackPos.line.int and gIdeCmd in {ideSug, ideCon}: L.cursor = CursorPosition.BeforeToken gTrackPos = L.previousToken gTrackPosAttached = true @@ -1066,7 +1066,7 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) = when defined(nimsuggest): # we attach the cursor to the last *strong* token if tok.tokType notin weakTokens: - L.previousToken.line = tok.line.int16 + L.previousToken.line = tok.line.uint16 L.previousToken.col = tok.col.int16 when defined(nimsuggest): @@ -1118,7 +1118,7 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) = tok.tokType = tkParLe when defined(nimsuggest): if L.fileIdx == gTrackPos.fileIndex and tok.col < gTrackPos.col and - tok.line == gTrackPos.line and gIdeCmd == ideCon: + tok.line == gTrackPos.line.int and gIdeCmd == ideCon: gTrackPos.col = tok.col.int16 of ')': tok.tokType = tkParRi @@ -1139,7 +1139,7 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) = of '.': when defined(nimsuggest): if L.fileIdx == gTrackPos.fileIndex and tok.col+1 == gTrackPos.col and - tok.line == gTrackPos.line and gIdeCmd == ideSug: + tok.line == gTrackPos.line.int and gIdeCmd == ideSug: tok.tokType = tkDot L.cursor = CursorPosition.InToken gTrackPos.col = tok.col.int16 diff --git a/compiler/main.nim b/compiler/main.nim index c928c81cd..401099fc3 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -35,7 +35,7 @@ proc writeDepsFile(g: ModuleGraph; project: string) = let f = open(changeFileExt(project, "deps"), fmWrite) for m in g.modules: if m != nil: - f.writeLine(toFullPath(m.position.int32)) + f.writeLine(toFullPath(m.position.FileIndex)) for k in g.inclToMod.keys: if g.getModule(k).isNil: # don't repeat includes which are also modules f.writeLine(k.toFullPath) @@ -265,7 +265,7 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) = of "parse": gCmd = cmdParse wantMainModule() - discard parseFile(gProjectMainIdx, cache) + discard parseFile(FileIndex gProjectMainIdx, cache) of "scan": gCmd = cmdScan wantMainModule() diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index 2c59a9097..6c14a46e8 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -25,7 +25,7 @@ ## - Its dependent module stays the same. ## -import ast, intsets, tables, options, rod +import ast, intsets, tables, options, rod, msgs, hashes type ModuleGraph* = ref object @@ -34,10 +34,10 @@ type deps*: IntSet # the dependency graph or potentially its transitive closure. suggestMode*: bool # whether we are in nimsuggest mode or not. invalidTransitiveClosure: bool - inclToMod*: Table[int32, int32] # mapping of include file to the - # first module that included it - importStack*: seq[int32] # The current import stack. Used for detecting recursive - # module dependencies. + inclToMod*: Table[FileIndex, FileIndex] # mapping of include file to the + # first module that included it + importStack*: seq[FileIndex] # The current import stack. Used for detecting recursive + # module dependencies. backend*: RootRef # minor hack so that a backend can extend this easily config*: ConfigRef doStopCompile*: proc(): bool {.closure.} @@ -45,6 +45,8 @@ type owners*: seq[PSym] methods*: seq[tuple[methods: TSymSeq, dispatcher: PSym]] +proc hash*(x: FileIndex): Hash {.borrow.} + {.this: g.} proc stopCompile*(g: ModuleGraph): bool {.inline.} = @@ -56,7 +58,7 @@ proc newModuleGraph*(config: ConfigRef = nil): ModuleGraph = result.deps = initIntSet() result.modules = @[] result.importStack = @[] - result.inclToMod = initTable[int32, int32]() + result.inclToMod = initTable[FileIndex, FileIndex]() if config.isNil: result.config = newConfigRef() else: @@ -69,35 +71,35 @@ proc resetAllModules*(g: ModuleGraph) = deps = initIntSet() modules = @[] importStack = @[] - inclToMod = initTable[int32, int32]() + inclToMod = initTable[FileIndex, FileIndex]() usageSym = nil owners = @[] methods = @[] -proc getModule*(g: ModuleGraph; fileIdx: int32): PSym = - if fileIdx >= 0 and fileIdx < modules.len: - result = modules[fileIdx] +proc getModule*(g: ModuleGraph; fileIdx: FileIndex): PSym = + if fileIdx.int32 >= 0 and fileIdx.int32 < modules.len: + result = modules[fileIdx.int32] proc dependsOn(a, b: int): int {.inline.} = (a shl 15) + b -proc addDep*(g: ModuleGraph; m: PSym, dep: int32) = - assert m.position == m.info.fileIndex +proc addDep*(g: ModuleGraph; m: PSym, dep: FileIndex) = + assert m.position == m.info.fileIndex.int32 addModuleDep(m.info.fileIndex, dep, isIncludeFile = false) if suggestMode: - deps.incl m.position.dependsOn(dep) + deps.incl m.position.dependsOn(dep.int) # we compute the transitive closure later when quering the graph lazily. # this improve efficiency quite a lot: #invalidTransitiveClosure = true -proc addIncludeDep*(g: ModuleGraph; module, includeFile: int32) = +proc addIncludeDep*(g: ModuleGraph; module, includeFile: FileIndex) = addModuleDep(module, includeFile, isIncludeFile = true) discard hasKeyOrPut(inclToMod, includeFile, module) -proc parentModule*(g: ModuleGraph; fileIdx: int32): int32 = +proc parentModule*(g: ModuleGraph; fileIdx: FileIndex): FileIndex = ## returns 'fileIdx' if the file belonging to this index is ## directly used as a module or else the module that first ## references this include file. - if fileIdx >= 0 and fileIdx < modules.len and modules[fileIdx] != nil: + if fileIdx.int32 >= 0 and fileIdx.int32 < modules.len and modules[fileIdx.int32] != nil: result = fileIdx else: result = inclToMod.getOrDefault(fileIdx) @@ -111,11 +113,11 @@ proc transitiveClosure(g: var IntSet; n: int) = if g.contains(i.dependsOn(k)) and g.contains(k.dependsOn(j)): g.incl i.dependsOn(j) -proc markDirty*(g: ModuleGraph; fileIdx: int32) = +proc markDirty*(g: ModuleGraph; fileIdx: FileIndex) = let m = getModule fileIdx if m != nil: incl m.flags, sfDirty -proc markClientsDirty*(g: ModuleGraph; fileIdx: int32) = +proc markClientsDirty*(g: ModuleGraph; fileIdx: FileIndex) = # we need to mark its dependent modules D as dirty right away because after # nimsuggest is done with this module, the module's dirty flag will be # cleared but D still needs to be remembered as 'dirty'. @@ -126,7 +128,7 @@ proc markClientsDirty*(g: ModuleGraph; fileIdx: int32) = # every module that *depends* on this file is also dirty: for i in 0i32..=% L: result = unknownLineInfo() else: result = msgContext[i] -template toFilename*(fileIdx: int32): string = - (if fileIdx < 0: "???" else: fileInfos[fileIdx].projPath) +template toFilename*(fileIdx: FileIndex): string = + (if fileIdx.int32 < 0: "???" else: fileInfos[fileIdx.int32].projPath) -proc toFullPath*(fileIdx: int32): string = - if fileIdx < 0: result = "???" - else: result = fileInfos[fileIdx].fullPath +proc toFullPath*(fileIdx: FileIndex): string = + if fileIdx.int32 < 0: result = "???" + else: result = fileInfos[fileIdx.int32].fullPath -proc setDirtyFile*(fileIdx: int32; filename: string) = - assert fileIdx >= 0 - fileInfos[fileIdx].dirtyFile = filename +proc setDirtyFile*(fileIdx: FileIndex; filename: string) = + assert fileIdx.int32 >= 0 + fileInfos[fileIdx.int32].dirtyFile = filename -proc setHash*(fileIdx: int32; hash: string) = - assert fileIdx >= 0 - shallowCopy(fileInfos[fileIdx].hash, hash) +proc setHash*(fileIdx: FileIndex; hash: string) = + assert fileIdx.int32 >= 0 + shallowCopy(fileInfos[fileIdx.int32].hash, hash) -proc getHash*(fileIdx: int32): string = - assert fileIdx >= 0 - shallowCopy(result, fileInfos[fileIdx].hash) +proc getHash*(fileIdx: FileIndex): string = + assert fileIdx.int32 >= 0 + shallowCopy(result, fileInfos[fileIdx.int32].hash) -proc toFullPathConsiderDirty*(fileIdx: int32): string = - if fileIdx < 0: +proc toFullPathConsiderDirty*(fileIdx: FileIndex): string = + if fileIdx.int32 < 0: result = "???" - elif not fileInfos[fileIdx].dirtyFile.isNil: - result = fileInfos[fileIdx].dirtyFile + elif not fileInfos[fileIdx.int32].dirtyFile.isNil: + result = fileInfos[fileIdx.int32].dirtyFile else: - result = fileInfos[fileIdx].fullPath + result = fileInfos[fileIdx.int32].fullPath template toFilename*(info: TLineInfo): string = info.fileIndex.toFilename @@ -762,15 +765,15 @@ template toFullPath*(info: TLineInfo): string = info.fileIndex.toFullPath proc toMsgFilename*(info: TLineInfo): string = - if info.fileIndex < 0: + if info.fileIndex.int32 < 0: result = "???" elif gListFullPaths: - result = fileInfos[info.fileIndex].fullPath + result = fileInfos[info.fileIndex.int32].fullPath else: - result = fileInfos[info.fileIndex].projPath + result = fileInfos[info.fileIndex.int32].projPath proc toLinenumber*(info: TLineInfo): int {.inline.} = - result = info.line + result = int info.line proc toColumn*(info: TLineInfo): int {.inline.} = result = info.col @@ -787,7 +790,7 @@ proc `??`* (info: TLineInfo, filename: string): bool = # only for debugging purposes result = filename in info.toFilename -const trackPosInvalidFileIdx* = -2 # special marker so that no suggestions +const trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions # are produced within comments and string literals var gTrackPos*: TLineInfo var gTrackPosAttached*: bool ## whether the tracking position was attached to some @@ -926,7 +929,7 @@ proc writeContext(lastinfo: TLineInfo) = else: styledMsgWriteln(styleBright, PosFormat % [toMsgFilename(msgContext[i]), - coordToStr(msgContext[i].line), + coordToStr(msgContext[i].line.int), coordToStr(msgContext[i].col+1)], resetStyle, getMessageStr(errInstantiationFrom, "")) @@ -994,7 +997,7 @@ proc formatMsg*(info: TLineInfo, msg: TMsgKind, arg: string): string = of warnMin..warnMax: WarningTitle of hintMin..hintMax: HintTitle else: ErrorTitle - result = PosFormat % [toMsgFilename(info), coordToStr(info.line), + result = PosFormat % [toMsgFilename(info), coordToStr(info.line.int), coordToStr(info.col+1)] & title & getMessageStr(msg, arg) @@ -1035,7 +1038,7 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string, # NOTE: currently line info line numbers start with 1, # but column numbers start with 0, however most editors expect # first column to be 1, so we need to +1 here - let x = PosFormat % [toMsgFilename(info), coordToStr(info.line), + let x = PosFormat % [toMsgFilename(info), coordToStr(info.line.int), coordToStr(info.col+1)] let s = getMessageStr(msg, arg) @@ -1093,30 +1096,30 @@ template assertNotNil*(e): untyped = template internalAssert*(e: bool) = if not e: internalError($instantiationInfo()) -proc addSourceLine*(fileIdx: int32, line: string) = - fileInfos[fileIdx].lines.add line.rope +proc addSourceLine*(fileIdx: FileIndex, line: string) = + fileInfos[fileIdx.int32].lines.add line.rope proc sourceLine*(i: TLineInfo): Rope = - if i.fileIndex < 0: return nil + if i.fileIndex.int32 < 0: return nil - if not optPreserveOrigSource and fileInfos[i.fileIndex].lines.len == 0: + if not optPreserveOrigSource and fileInfos[i.fileIndex.int32].lines.len == 0: try: for line in lines(i.toFullPath): addSourceLine i.fileIndex, line.string except IOError: discard - internalAssert i.fileIndex < fileInfos.len + internalAssert i.fileIndex.int32 < fileInfos.len # can happen if the error points to EOF: - if i.line > fileInfos[i.fileIndex].lines.len: return nil + if i.line.int > fileInfos[i.fileIndex.int32].lines.len: return nil - result = fileInfos[i.fileIndex].lines[i.line-1] + result = fileInfos[i.fileIndex.int32].lines[i.line.int-1] proc quotedFilename*(i: TLineInfo): Rope = - internalAssert i.fileIndex >= 0 + internalAssert i.fileIndex.int32 >= 0 if optExcessiveStackTrace in gGlobalOptions: - result = fileInfos[i.fileIndex].quotedFullName + result = fileInfos[i.fileIndex.int32].quotedFullName else: - result = fileInfos[i.fileIndex].quotedName + result = fileInfos[i.fileIndex.int32].quotedName ropes.errorHandler = proc (err: RopesError, msg: string, useWarning: bool) = case err diff --git a/compiler/nimfix/pretty.nim b/compiler/nimfix/pretty.nim index 55603f4cd..4627264dc 100644 --- a/compiler/nimfix/pretty.nim +++ b/compiler/nimfix/pretty.nim @@ -28,7 +28,7 @@ proc overwriteFiles*() = let doStrip = options.getConfigVar("pretty.strip").normalize == "on" for i in 0 .. high(gSourceFiles): if gSourceFiles[i].dirty and not gSourceFiles[i].isNimfixFile and - (not gOnlyMainfile or gSourceFiles[i].fileIdx == gProjectMainIdx): + (not gOnlyMainfile or gSourceFiles[i].fileIdx == gProjectMainIdx.FileIndex): let newFile = if gOverWrite: gSourceFiles[i].fullpath else: gSourceFiles[i].fullpath.changeFileExt(".pretty.nim") try: @@ -95,7 +95,7 @@ proc beautifyName(s: string, k: TSymKind): string = proc replaceInFile(info: TLineInfo; newName: string) = loadFile(info) - let line = gSourceFiles[info.fileIndex].lines[info.line-1] + let line = gSourceFiles[info.fileIndex.int].lines[info.line.int-1] var first = min(info.col.int, line.len) if first < 0: return #inc first, skipIgnoreCase(line, "proc ", first) @@ -107,8 +107,8 @@ proc replaceInFile(info: TLineInfo; newName: string) = if differ(line, first, last, newName): # last-first+1 != newName.len or var x = line.substr(0, first-1) & newName & line.substr(last+1) - system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) - gSourceFiles[info.fileIndex].dirty = true + system.shallowCopy(gSourceFiles[info.fileIndex.int].lines[info.line.int-1], x) + gSourceFiles[info.fileIndex.int].dirty = true proc checkStyle(info: TLineInfo, s: string, k: TSymKind; sym: PSym) = let beau = beautifyName(s, k) @@ -136,7 +136,7 @@ template styleCheckDef*(s: PSym) = styleCheckDef(s.info, s, s.kind) proc styleCheckUseImpl(info: TLineInfo; s: PSym) = - if info.fileIndex < 0: return + if info.fileIndex.int < 0: return # we simply convert it to what it looks like in the definition # for consistency diff --git a/compiler/nimfix/prettybase.nim b/compiler/nimfix/prettybase.nim index f1d24183b..ecb4b0093 100644 --- a/compiler/nimfix/prettybase.nim +++ b/compiler/nimfix/prettybase.nim @@ -16,13 +16,13 @@ type lines*: seq[string] dirty*, isNimfixFile*: bool fullpath*, newline*: string - fileIdx*: int32 + fileIdx*: FileIndex var gSourceFiles*: seq[TSourceFile] = @[] proc loadFile*(info: TLineInfo) = - let i = info.fileIndex + let i = info.fileIndex.int if i >= gSourceFiles.len: gSourceFiles.setLen(i+1) if gSourceFiles[i].lines.isNil: @@ -64,7 +64,7 @@ proc differ*(line: string, a, b: int, x: string): bool = proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PIdent) = loadFile(info) - let line = gSourceFiles[info.fileIndex].lines[info.line-1] + let line = gSourceFiles[info.fileIndex.int32].lines[info.line.int-1] var first = min(info.col.int, line.len) if first < 0: return #inc first, skipIgnoreCase(line, "proc ", first) @@ -75,8 +75,8 @@ proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PIdent) = let last = first+identLen(line, first)-1 if cmpIgnoreStyle(line[first..last], oldSym.s) == 0: var x = line.substr(0, first-1) & newSym.s & line.substr(last+1) - system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) - gSourceFiles[info.fileIndex].dirty = true + system.shallowCopy(gSourceFiles[info.fileIndex.int32].lines[info.line.int-1], x) + gSourceFiles[info.fileIndex.int32].dirty = true #if newSym.s == "File": writeStackTrace() proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PSym) = @@ -85,10 +85,10 @@ proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PSym) = proc replaceComment*(info: TLineInfo) = loadFile(info) - let line = gSourceFiles[info.fileIndex].lines[info.line-1] + let line = gSourceFiles[info.fileIndex.int32].lines[info.line.int-1] var first = info.col.int if line[first] != '#': inc first var x = line.substr(0, first-1) & "discard " & line.substr(first+1).escape - system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x) - gSourceFiles[info.fileIndex].dirty = true + system.shallowCopy(gSourceFiles[info.fileIndex.int32].lines[info.line.int-1], x) + gSourceFiles[info.fileIndex.int32].dirty = true diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim index 8540f1b32..02c48c16d 100644 --- a/compiler/parampatterns.nim +++ b/compiler/parampatterns.nim @@ -235,7 +235,8 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult result = arLValue else: result = isAssignable(owner, n.sons[0], isUnsafeAddr) - if result != arNone and sfDiscriminant in n.sons[1].sym.flags: + if result != arNone and n[1].kind == nkSym and + sfDiscriminant in n[1].sym.flags: result = arDiscriminant of nkBracketExpr: if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind in diff --git a/compiler/parser.nim b/compiler/parser.nim index 3bf75c6f7..ac0a57770 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -83,7 +83,7 @@ proc getTok(p: var TParser) = rawGetTok(p.lex, p.tok) p.hasProgress = true -proc openParser*(p: var TParser, fileIdx: int32, inputStream: PLLStream, +proc openParser*(p: var TParser, fileIdx: FileIndex, inputStream: PLLStream, cache: IdentCache; strongSpaces=false) = ## Open a parser, using the given arguments to set up its internal state. diff --git a/compiler/passes.nim b/compiler/passes.nim index f079100ea..d7c181676 100644 --- a/compiler/passes.nim +++ b/compiler/passes.nim @@ -52,8 +52,8 @@ proc makePass*(open: TPassOpen = nil, # the semantic checker needs these: var - gImportModule*: proc (graph: ModuleGraph; m: PSym, fileIdx: int32; cache: IdentCache): PSym {.nimcall.} - gIncludeFile*: proc (graph: ModuleGraph; m: PSym, fileIdx: int32; cache: IdentCache): PNode {.nimcall.} + gImportModule*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex; cache: IdentCache): PSym {.nimcall.} + gIncludeFile*: proc (graph: ModuleGraph; m: PSym, fileIdx: FileIndex; cache: IdentCache): PNode {.nimcall.} # implementation @@ -63,20 +63,6 @@ proc skipCodegen*(n: PNode): bool {.inline.} = # error count instead. result = msgs.gErrorCounter > 0 -proc astNeeded*(s: PSym): bool = - # The ``rodwrite`` module uses this to determine if the body of a proc - # needs to be stored. The passes manager frees s.sons[codePos] when - # appropriate to free the procedure body's memory. This is important - # to keep memory usage down. - if (s.kind in {skMethod, skProc, skFunc}) and - ({sfCompilerProc, sfCompileTime} * s.flags == {}) and - (s.typ.callConv != ccInline) and - (s.ast.sons[genericParamsPos].kind == nkEmpty): - result = false - # XXX this doesn't really make sense with excessive CTFE - else: - result = true - const maxPasses = 10 @@ -153,7 +139,7 @@ proc closePassesCached(graph: ModuleGraph; a: var TPassContextArray) = m = gPasses[i].close(graph, a[i], m) a[i] = nil # free the memory here -proc resolveMod(module, relativeTo: string): int32 = +proc resolveMod(module, relativeTo: string): FileIndex = let fullPath = findModule(module, relativeTo) if fullPath.len == 0: result = InvalidFileIDX @@ -166,7 +152,7 @@ proc processImplicits(implicits: seq[string], nodeKind: TNodeKind, let relativeTo = m.info.toFullPath for module in items(implicits): # implicit imports should not lead to a module importing itself - if m.position != resolveMod(module, relativeTo): + if m.position != resolveMod(module, relativeTo).int32: var importStmt = newNodeI(nodeKind, gCmdLineInfo) var str = newStrNode(nkStrLit, module) str.info = gCmdLineInfo @@ -180,7 +166,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream, p: TParsers a: TPassContextArray s: PLLStream - fileIdx = module.fileIdx + fileIdx = FileIndex module.fileIdx if module.id < 0: # new module caching mechanism: for i in 0..= gMods.len: setLen(gMods, fileIdx+1) - gMods[fileIdx].hash = result + if fileIdx.int32 >= gMods.len: setLen(gMods, fileIdx.int32+1) + gMods[fileIdx.int32].hash = result template growCache*(cache, pos) = if cache.len <= pos: cache.setLen(pos+1) -proc checkDep(fileIdx: int32; cache: IdentCache): TReasonForRecompile = +proc checkDep(fileIdx: FileIndex; cache: IdentCache): TReasonForRecompile = assert fileIdx != InvalidFileIDX - growCache gMods, fileIdx - if gMods[fileIdx].reason != rrEmpty: + growCache gMods, fileIdx.int32 + if gMods[fileIdx.int32].reason != rrEmpty: # reason has already been computed for this module: - return gMods[fileIdx].reason + return gMods[fileIdx.int32].reason let filename = fileIdx.toFilename var hash = getHash(fileIdx) - gMods[fileIdx].reason = rrNone # we need to set it here to avoid cycles + gMods[fileIdx.int32].reason = rrNone # we need to set it here to avoid cycles result = rrNone var rodfile = toGeneratedFile(filename.withPackageName, RodExt) - var r = newRodReader(rodfile, hash, fileIdx, cache) + var r = newRodReader(rodfile, hash, fileIdx.int32, cache) if r == nil: result = (if existsFile(rodfile): rrRodInvalid else: rrRodDoesNotExist) else: @@ -907,19 +907,18 @@ proc checkDep(fileIdx: int32; cache: IdentCache): TReasonForRecompile = # recompilation is necessary: if r != nil: memfiles.close(r.memfile) r = nil - gMods[fileIdx].rd = r - gMods[fileIdx].reason = result # now we know better + gMods[fileIdx.int32].rd = r + gMods[fileIdx.int32].reason = result # now we know better proc handleSymbolFile*(module: PSym; cache: IdentCache): PRodReader = - let fileIdx = module.fileIdx if gSymbolFiles in {disabledSf, writeOnlySf, v2Sf}: module.id = getID() return nil idgen.loadMaxIds(options.gProjectPath / options.gProjectName) - + let fileIdx = FileIndex module.fileIdx discard checkDep(fileIdx, cache) - if gMods[fileIdx].reason == rrEmpty: internalError("handleSymbolFile") - result = gMods[fileIdx].rd + if gMods[fileIdx.int32].reason == rrEmpty: internalError("handleSymbolFile") + result = gMods[fileIdx.int32].rd if result != nil: module.id = result.moduleID result.syms[module.id] = module @@ -1153,7 +1152,7 @@ proc viewFile(rodfile: string) = if r.s[r.pos] == '\x0A': inc(r.pos) inc(r.line) - outf.write(w, " ", inclHash, "\n") + outf.write(w.int32, " ", inclHash, "\n") if r.s[r.pos] == ')': inc(r.pos) outf.write(")\n") of "DEPS": @@ -1163,7 +1162,7 @@ proc viewFile(rodfile: string) = let v = int32(decodeVInt(r.s, r.pos)) r.modDeps.add(r.files[v]) if r.s[r.pos] == ' ': inc(r.pos) - outf.write(" ", r.files[v]) + outf.write(" ", r.files[v].int32) outf.write("\n") of "INTERF", "COMPILERPROCS": inc r.pos, 2 diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim index 96deb1d5a..0ae687268 100644 --- a/compiler/rodwrite.nim +++ b/compiler/rodwrite.nim @@ -55,7 +55,7 @@ proc fileIdx(w: PRodWriter, filename: string): int = w.files[result] = filename template filename*(w: PRodWriter): string = - w.module.filename + toFilename(FileIndex w.module.position) proc newRodWriter(hash: SecureHash, module: PSym; cache: IdentCache): PRodWriter = new(result) @@ -125,14 +125,14 @@ proc encodeNode(w: PRodWriter, fInfo: TLineInfo, n: PNode, result.add('?') encodeVInt(n.info.col, result) result.add(',') - encodeVInt(n.info.line, result) + encodeVInt(int n.info.line, result) result.add(',') encodeVInt(fileIdx(w, toFullPath(n.info)), result) elif fInfo.line != n.info.line: result.add('?') encodeVInt(n.info.col, result) result.add(',') - encodeVInt(n.info.line, result) + encodeVInt(int n.info.line, result) elif fInfo.col != n.info.col: result.add('?') encodeVInt(n.info.col, result) @@ -303,7 +303,7 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) = result.add('?') if s.info.col != -1'i16: encodeVInt(s.info.col, result) result.add(',') - if s.info.line != -1'i16: encodeVInt(s.info.line, result) + if s.info.line != 0'u16: encodeVInt(int s.info.line, result) result.add(',') encodeVInt(fileIdx(w, toFullPath(s.info)), result) if s.owner != nil: @@ -642,7 +642,7 @@ proc process(c: PPassContext, n: PNode): PNode = proc myOpen(g: ModuleGraph; module: PSym; cache: IdentCache): PPassContext = if module.id < 0: internalError("rodwrite: module ID not set") - var w = newRodWriter(rodread.getHash module.fileIdx, module, cache) + var w = newRodWriter(rodread.getHash FileIndex module.position, module, cache) rawAddInterfaceSym(w, module) result = w diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 3996188dc..bcc1bba15 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -144,7 +144,7 @@ proc makeInstPair*(s: PSym, inst: PInstantiation): TInstantiationPair = proc filename*(c: PContext): string = # the module's filename - return c.module.filename + return toFilename(FileIndex c.module.position) proc scopeDepth*(c: PContext): int {.inline.} = result = if c.currentScope != nil: c.currentScope.depthLevel diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 75d8cc2e0..8d7747fb4 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1095,12 +1095,12 @@ proc semAllTypeSections(c: PContext; n: PNode): PNode = for i in 0.. 0: suggestQuit() proc suggestSentinel*(c: PContext) = - if gIdeCmd != ideSug or c.module.position != gTrackPos.fileIndex: return + if gIdeCmd != ideSug or c.module.position != gTrackPos.fileIndex.int32: return if c.compilesContextId > 0: return inc(c.compilesContextId) var outputs: Suggestions = @[] diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim index 4745b1ac7..4014d4c58 100644 --- a/compiler/syntaxes.nim +++ b/compiler/syntaxes.nim @@ -138,7 +138,7 @@ proc evalPipe(p: var TParsers, n: PNode, filename: string, else: result = applyFilter(p, n, filename, result) -proc openParsers*(p: var TParsers, fileIdx: int32, inputstream: PLLStream; +proc openParsers*(p: var TParsers, fileIdx: FileIndex, inputstream: PLLStream; cache: IdentCache) = var s: PLLStream p.skin = skinStandard @@ -155,7 +155,7 @@ proc openParsers*(p: var TParsers, fileIdx: int32, inputstream: PLLStream; proc closeParsers*(p: var TParsers) = parser.closeParser(p.parser) -proc parseFile*(fileIdx: int32; cache: IdentCache): PNode {.procvar.} = +proc parseFile*(fileIdx: FileIndex; cache: IdentCache): PNode {.procvar.} = var p: TParsers f: File diff --git a/compiler/vm.nim b/compiler/vm.nim index 5b5ccdce4..70f79c433 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1381,7 +1381,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcNGetLine: decodeB(rkNode) let n = regs[rb].node - regs[ra].node = newIntNode(nkIntLit, n.info.line) + regs[ra].node = newIntNode(nkIntLit, n.info.line.int) regs[ra].node.info = n.info regs[ra].node.typ = n.typ of opcNGetColumn: @@ -1521,7 +1521,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let x = newNodeI(TNodeKind(int(k)), if cc.kind != nkNilLit: cc.info - elif c.comesFromHeuristic.line > -1: + elif c.comesFromHeuristic.line != 0'u16: c.comesFromHeuristic elif c.callsite != nil and c.callsite.safeLen > 1: c.callsite[1].info @@ -1748,7 +1748,7 @@ proc evalMacroCall*(module: PSym; cache: IdentCache, n, nOrig: PNode, setupGlobalCtx(module, cache) var c = globalCtx - c.comesFromHeuristic.line = -1 + c.comesFromHeuristic.line = 0'u16 c.callsite = nOrig let start = genProc(c, sym) -- cgit 1.4.1-2-gfad0 From 72dfe176f5211f561263984a2df653f16dcf5466 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Mon, 23 Apr 2018 17:02:38 +0800 Subject: remove dead code elimination option (#7669) --- compiler/ast.nim | 6 +++--- compiler/ccgexprs.nim | 5 ++--- compiler/ccgstmts.nim | 18 ++---------------- compiler/ccgutils.nim | 4 ---- compiler/cgen.nim | 4 ---- compiler/commands.nim | 3 +-- compiler/options.nim | 3 ++- compiler/pragmas.nim | 14 ++++---------- compiler/wordrecg.nim | 6 ++++-- doc/basicopt.txt | 1 - doc/manual.rst | 16 ---------------- doc/nimc.rst | 4 ++-- lib/deprecated/pure/sockets.nim | 2 +- lib/impure/db_sqlite.nim | 2 +- lib/impure/rdstdin.nim | 2 +- lib/posix/epoll.nim | 2 +- lib/posix/inotify.nim | 2 +- lib/posix/kqueue.nim | 8 +++----- lib/posix/linux.nim | 2 +- lib/posix/posix.nim | 8 ++++---- lib/posix/posix_other.nim | 2 +- lib/posix/termios.nim | 2 +- lib/pure/fenv.nim | 2 +- lib/pure/matchers.nim | 2 +- lib/pure/net.nim | 2 +- lib/pure/os.nim | 2 +- lib/pure/parseutils.nim | 2 +- lib/pure/ropes.nim | 2 +- lib/pure/strmisc.nim | 2 +- lib/pure/strutils.nim | 2 +- lib/pure/unicode.nim | 2 +- lib/system.nim | 2 +- lib/windows/winlean.nim | 2 +- lib/wrappers/iup.nim | 2 +- lib/wrappers/mysql.nim | 2 +- lib/wrappers/odbcsql.nim | 2 +- lib/wrappers/openssl.nim | 2 +- lib/wrappers/pcre.nim | 2 +- lib/wrappers/postgres.nim | 2 +- lib/wrappers/sqlite3.nim | 2 +- tests/enum/toptions.nim | 2 +- tests/iter/tobj_iter.nim | 2 -- .../keineschweine/dependencies/chipmunk/chipmunk.nim | 1 - tests/manyloc/keineschweine/dependencies/enet/enet.nim | 1 - .../keineschweine/dependencies/genpacket/macro_dsl.nim | 2 +- tests/manyloc/keineschweine/dependencies/sfml/sfml.nim | 2 +- .../keineschweine/dependencies/sfml/sfml_colors.nim | 2 +- .../keineschweine/dependencies/sfml/sfml_vector.nim | 1 - tests/manyloc/keineschweine/keineschweine.nim | 2 +- tests/manyloc/keineschweine/lib/sg_gui.nim | 2 +- tests/manyloc/keineschweine/server/nim.cfg | 1 - tests/manyloc/nake/nakefile.nim | 2 +- tests/manyloc/standalone/barebone.nim.cfg | 1 - tests/pragmas/tnoreturn.nim | 7 +++++-- tests/rodfiles/deadg.nim | 3 --- tools/nim.bash-completion | 4 ++-- tools/nim.zsh-completion | 2 -- 57 files changed, 67 insertions(+), 122 deletions(-) (limited to 'compiler/pragmas.nim') diff --git a/compiler/ast.nim b/compiler/ast.nim index 4a0a9a20b..2c8f686eb 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -262,7 +262,8 @@ type # variable is a thread variable sfCompileTime, # proc can be evaluated at compile time sfConstructor, # proc is a C++ constructor - sfDeadCodeElim, # dead code elimination for the module is turned on + sfDispatcher, # copied method symbol is the dispatcher + # deprecated and unused, except for the con sfBorrow, # proc is borrowed sfInfixCall, # symbol needs infix call syntax in target language; # for interfacing with C++, JS @@ -275,10 +276,9 @@ type TSymFlags* = set[TSymFlag] const - sfDispatcher* = sfDeadCodeElim # copied method symbol is the dispatcher sfNoInit* = sfMainModule # don't generate code to init the variable - sfImmediate* = sfDeadCodeElim + sfImmediate* = sfDispatcher # macro or template is immediately expanded # without considering any possible overloads sfAllUntyped* = sfVolatile # macro or template is immediately expanded \ diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 461a86298..ea373f5a6 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2264,7 +2264,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = of nkEmpty: discard of nkWhileStmt: genWhileStmt(p, n) of nkVarSection, nkLetSection: genVarStmt(p, n) - of nkConstSection: genConstStmt(p, n) + of nkConstSection: discard # consts generated lazily on use of nkForStmt: internalError(n.info, "for statement not eliminated") of nkCaseStmt: genCase(p, n, d) of nkReturnStmt: genReturnStmt(p, n) @@ -2315,8 +2315,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = # are not transformed correctly. We work around this issue (#411) here # by ensuring it's no inner proc (owner is a module): if prc.skipGenericOwner.kind == skModule and sfCompileTime notin prc.flags: - if (not emitLazily(prc)) or - ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or + if ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or (sfExportc in prc.flags and lfExportLib in prc.loc.flags) or (prc.kind == skMethod): # we have not only the header: diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 2030d6add..cb3d6dbe6 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -280,20 +280,6 @@ proc genVarStmt(p: BProc, n: PNode) = else: genVarTuple(p, it) -proc genConstStmt(p: BProc, n: PNode) = - for it in n.sons: - if it.kind == nkCommentStmt: continue - if it.kind != nkConstDef: internalError(n.info, "genConstStmt") - - let sym = it.sons[0].sym - if sym.typ.containsCompileTimeOnly or - sym.typ.kind notin ConstantDataTypes or - sym.ast.len == 0 or - emitLazily(sym): - continue - - requestConstImpl(p, sym) - proc genIf(p: BProc, n: PNode, d: var TLoc) = # # { if (!expr1) goto L1; @@ -587,7 +573,7 @@ proc genRaiseStmt(p: BProc, t: PNode) = genLineDir(p, t) if isImportedException(typ): lineF(p, cpsStmts, "throw $1;$n", [e]) - else: + else: lineCg(p, cpsStmts, "#raiseException((#Exception*)$1, $2);$n", [e, makeCString(typ.sym.name.s)]) else: @@ -836,7 +822,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = else: for j in 0..t[i].len-2: if t[i][j].isInfixAs(): - let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:` + let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:` fillLoc(exvar.sym.loc, locTemp, exvar, mangleLocalName(p, exvar.sym), OnUnknown) startBlock(p, "catch ($1& $2) {$n", getTypeDesc(p.module, t[i][j][1].typ), rdLoc(exvar.sym.loc)) else: diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index fe28d2209..48648bdde 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -211,8 +211,4 @@ proc mangle*(name: string): string = if requiresUnderscore: result.add "_" -proc emitLazily*(s: PSym): bool {.inline.} = - result = optDeadCodeElim in gGlobalOptions or - sfDeadCodeElim in getModule(s).flags - initTypeTables() diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 9e1f9349f..ff3e6714d 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1309,10 +1309,6 @@ proc newModule(g: BModuleList; module: PSym): BModule = growCache g.modules, module.position g.modules[module.position] = result - if (optDeadCodeElim in gGlobalOptions): - if (sfDeadCodeElim in module.flags): - internalError("added pending module twice: " & toFilename(FileIndex module.position)) - template injectG(config) {.dirty.} = if graph.backend == nil: graph.backend = newModuleList(config) diff --git a/compiler/commands.nim b/compiler/commands.nim index e1dc1aacf..8d73ac90e 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -268,7 +268,6 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool = of "movechecks": result = contains(gOptions, optMoveCheck) of "linedir": result = contains(gOptions, optLineDir) of "assertions", "a": result = contains(gOptions, optAssert) - of "deadcodeelim": result = contains(gGlobalOptions, optDeadCodeElim) of "run", "r": result = contains(gGlobalOptions, optRun) of "symbolfiles": result = gSymbolFiles != disabledSf of "genscript": result = contains(gGlobalOptions, optGenScript) @@ -509,7 +508,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "movechecks": processOnOffSwitch({optMoveCheck}, arg, pass, info) of "linedir": processOnOffSwitch({optLineDir}, arg, pass, info) of "assertions", "a": processOnOffSwitch({optAssert}, arg, pass, info) - of "deadcodeelim": processOnOffSwitchG({optDeadCodeElim}, arg, pass, info) + of "deadcodeelim": discard # deprecated, dead code elim always on of "threads": processOnOffSwitchG({optThreads}, arg, pass, info) #if optThreads in gGlobalOptions: incl(gNotes, warnGcUnsafe) diff --git a/compiler/options.nim b/compiler/options.nim index 93a3f1796..7126d4398 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -41,7 +41,8 @@ type # please make sure we have under 32 options TOptions* = set[TOption] TGlobalOption* = enum # **keep binary compatible** - gloptNone, optForceFullMake, optDeadCodeElim, + gloptNone, optForceFullMake, + optDeadCodeElimUnused, # deprecated, always on optListCmd, optCompileOnly, optNoLinking, optCDebug, # turn on debugging information optGenDynLib, # generate a dynamic library diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index cb11564a4..9e9233fe7 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -44,7 +44,9 @@ const wWarnings, wHints, wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError, wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop, - wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated, + wBreakpoint, wWatchPoint, wPassl, wPassc, + wDeadCodeElimUnused, # deprecated, always on + wDeprecated, wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll, wLinearScanEnd, wPatterns, wEffects, wNoForward, wReorder, wComputedGoto, wInjectStmt, wDeprecated, wExperimental, wThis} @@ -215,10 +217,6 @@ proc onOff(c: PContext, n: PNode, op: TOptions) = if isTurnedOn(c, n): gOptions = gOptions + op else: gOptions = gOptions - op -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; flag=sfNoForward) = if isTurnedOn(c, n): incl(c.module.flags, flag) else: excl(c.module.flags, flag) @@ -764,7 +762,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, of wThreadVar: noVal(it) incl(sym.flags, sfThread) - of wDeadCodeElim: pragmaDeadCodeElim(c, it) + of wDeadCodeElimUnused: discard # deprecated, dead code elim always on of wNoForward: pragmaNoForward(c, it) of wReorder: pragmaNoForward(c, it, sfReorder) of wMagic: processMagic(c, it, sym) @@ -960,10 +958,6 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, if sym.kind != skType or sym.typ == nil: invalidPragma(it) else: incl(sym.typ.flags, tfPartial) - # .partial types can only work with dead code elimination - # to prevent the codegen from doing anything before we compiled - # the whole program: - incl gGlobalOptions, optDeadCodeElim of wInject, wGensym: # We check for errors, but do nothing with these pragmas otherwise # as they are handled directly in 'evalTemplate'. diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim index 76d91d4e7..91b527e02 100644 --- a/compiler/wordrecg.nim +++ b/compiler/wordrecg.nim @@ -55,7 +55,8 @@ type wFloatchecks, wNanChecks, wInfChecks, wMoveChecks, wAssertions, wPatterns, wWarnings, wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags, - wDeadCodeElim, wSafecode, wPackage, wNoForward, wReorder, wNoRewrite, + wDeadCodeElimUnused, # deprecated, dead code elim always happens + wSafecode, wPackage, wNoForward, wReorder, wNoRewrite, wPragma, wCompileTime, wNoInit, wPassc, wPassl, wBorrow, wDiscardable, @@ -143,7 +144,8 @@ const "assertions", "patterns", "warnings", "hints", "optimization", "raises", "writes", "reads", "size", "effects", "tags", - "deadcodeelim", "safecode", "package", "noforward", "reorder", "norewrite", + "deadcodeelim", # deprecated, dead code elim always happens + "safecode", "package", "noforward", "reorder", "norewrite", "pragma", "compiletime", "noinit", "passc", "passl", "borrow", "discardable", "fieldchecks", diff --git a/doc/basicopt.txt b/doc/basicopt.txt index 4c11cc767..90c7ba09c 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -29,7 +29,6 @@ Options: --nanChecks:on|off turn NaN checks on|off --infChecks:on|off turn Inf checks on|off --nilChecks:on|off turn nil checks on|off - --deadCodeElim:on|off whole program dead code elimination on|off --opt:none|speed|size optimize not at all or for speed|size Note: use -d:release for a release build! --debugger:native|endb use native debugger (gdb) | ENDB (experimental) diff --git a/doc/manual.rst b/doc/manual.rst index fbd043020..f1330d524 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -6768,22 +6768,6 @@ the created global variables within a module is not defined, but all of them will be initialized after any top-level variables in their originating module and before any variable in a module that imports it. -deadCodeElim pragma -------------------- -The ``deadCodeElim`` pragma only applies to whole modules: It tells the -compiler to activate (or deactivate) dead code elimination for the module the -pragma appears in. - -The ``--deadCodeElim:on`` command line switch has the same effect as marking -every module with ``{.deadCodeElim:on}``. However, for some modules such as -the GTK wrapper it makes sense to *always* turn on dead code elimination - -no matter if it is globally active or not. - -Example: - -.. code-block:: nim - {.deadCodeElim: on.} - .. NoForward pragma diff --git a/doc/nimc.rst b/doc/nimc.rst index b275438ea..29dbdea42 100644 --- a/doc/nimc.rst +++ b/doc/nimc.rst @@ -181,7 +181,7 @@ generated; use the ``--symbolFiles:on`` command line switch to activate them. Unfortunately due to technical reasons the ``--symbolFiles:on`` needs to *aggregate* some generated C code. This means that the resulting executable -might contain some cruft even when dead code elimination is turned on. So +might contain some cruft even with dead code elimination. So the final release build should be done with ``--symbolFiles:off``. Due to the aggregation of C code it is also recommended that each project @@ -439,7 +439,7 @@ target. For example, to generate code for an `AVR`:idx: processor use this command:: - nim c --cpu:avr --os:standalone --deadCodeElim:on --genScript x.nim + nim c --cpu:avr --os:standalone --genScript x.nim For the ``standalone`` target one needs to provide a file ``panicoverride.nim``. diff --git a/lib/deprecated/pure/sockets.nim b/lib/deprecated/pure/sockets.nim index f0568366a..05aebef76 100644 --- a/lib/deprecated/pure/sockets.nim +++ b/lib/deprecated/pure/sockets.nim @@ -32,7 +32,7 @@ include "system/inclrtl" -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated when hostOS == "solaris": {.passl: "-lsocket -lnsl".} diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim index 21049571f..f88037e2f 100644 --- a/lib/impure/db_sqlite.nim +++ b/lib/impure/db_sqlite.nim @@ -81,7 +81,7 @@ ## ## theDb.close() -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated import strutils, sqlite3 diff --git a/lib/impure/rdstdin.nim b/lib/impure/rdstdin.nim index 5aa4cfcc3..54bab82f0 100644 --- a/lib/impure/rdstdin.nim +++ b/lib/impure/rdstdin.nim @@ -13,7 +13,7 @@ ## is used. This suffices because Windows' console already provides the ## wanted functionality. -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated when defined(Windows): proc readLineFromStdin*(prompt: string): TaintedString {. diff --git a/lib/posix/epoll.nim b/lib/posix/epoll.nim index c5ed1a873..2d38137bb 100644 --- a/lib/posix/epoll.nim +++ b/lib/posix/epoll.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated from posix import SocketHandle diff --git a/lib/posix/inotify.nim b/lib/posix/inotify.nim index a206f8067..359e88617 100644 --- a/lib/posix/inotify.nim +++ b/lib/posix/inotify.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated # Get the platform-dependent flags. # Structure describing an inotify event. diff --git a/lib/posix/kqueue.nim b/lib/posix/kqueue.nim index 730491a53..18b47f5d5 100644 --- a/lib/posix/kqueue.nim +++ b/lib/posix/kqueue.nim @@ -7,8 +7,6 @@ # distribution, for details about the copyright. # -{.deadCodeElim:on.} - from posix import Timespec when defined(macosx) or defined(freebsd) or defined(openbsd) or @@ -61,7 +59,7 @@ const EV_CLEAR* = 0x0020 ## Clear event state after reporting. EV_RECEIPT* = 0x0040 ## Force EV_ERROR on success, data == 0 EV_DISPATCH* = 0x0080 ## Disable event after reporting. - + EV_SYSFLAGS* = 0xF000 ## Reserved by system EV_DROP* = 0x1000 ## Not should be dropped EV_FLAG1* = 0x2000 ## Filter-specific flag @@ -87,10 +85,10 @@ when defined(macosx) or defined(freebsd) or defined(dragonfly): NOTE_FFAND* = 0x40000000'u32 ## AND fflags NOTE_FFOR* = 0x80000000'u32 ## OR fflags NOTE_FFCOPY* = 0xc0000000'u32 ## copy fflags - NOTE_FFCTRLMASK* = 0xc0000000'u32 ## masks for operations + NOTE_FFCTRLMASK* = 0xc0000000'u32 ## masks for operations NOTE_FFLAGSMASK* = 0x00ffffff'u32 - NOTE_TRIGGER* = 0x01000000'u32 ## Cause the event to be triggered + NOTE_TRIGGER* = 0x01000000'u32 ## Cause the event to be triggered ## for output. # data/hint flags for EVFILT_{READ|WRITE}, shared with userspace diff --git a/lib/posix/linux.nim b/lib/posix/linux.nim index 6f9f75e34..25c7c7979 100644 --- a/lib/posix/linux.nim +++ b/lib/posix/linux.nim @@ -1,4 +1,4 @@ -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated import posix diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim index a23d76050..3ff156bdf 100644 --- a/lib/posix/posix.nim +++ b/lib/posix/posix.nim @@ -27,10 +27,10 @@ ## resulting C code will just ``#include `` and *not* define the ## symbols declared here. -# This ensures that we don't accidentally generate #includes for files that -# might not exist on a specific platform! The user will get an error only -# if they actualy try to use the missing declaration -{.deadCodeElim: on.} +# Dead code elimination ensures that we don't accidentally generate #includes +# for files that might not exist on a specific platform! The user will get an +# error only if they actualy try to use the missing declaration +{.deadCodeElim: on.} # dce option deprecated # TODO these constants don't seem to be fetched from a header file for unknown # platforms - where do they come from and why are they here? diff --git a/lib/posix/posix_other.nim b/lib/posix/posix_other.nim index ae41263e8..004a4205b 100644 --- a/lib/posix/posix_other.nim +++ b/lib/posix/posix_other.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated const hasSpawnH = not defined(haiku) # should exist for every Posix system nowadays diff --git a/lib/posix/termios.nim b/lib/posix/termios.nim index f86e408fb..60d540107 100644 --- a/lib/posix/termios.nim +++ b/lib/posix/termios.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated import posix type diff --git a/lib/pure/fenv.nim b/lib/pure/fenv.nim index f8f115ecc..a083c680c 100644 --- a/lib/pure/fenv.nim +++ b/lib/pure/fenv.nim @@ -10,7 +10,7 @@ ## Floating-point environment. Handling of floating-point rounding and ## exceptions (overflow, division by zero, etc.). -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated when defined(Posix) and not defined(haiku): {.passl: "-lm".} diff --git a/lib/pure/matchers.nim b/lib/pure/matchers.nim index 6366fee1a..685c3b07a 100644 --- a/lib/pure/matchers.nim +++ b/lib/pure/matchers.nim @@ -12,7 +12,7 @@ ## **Warning:** This module is deprecated since version 0.14.0. {.deprecated.} -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated {.push debugger:off .} # the user does not want to trace a part # of the standard library! diff --git a/lib/pure/net.nim b/lib/pure/net.nim index ccf02a1fc..ebb59ca6d 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -68,7 +68,7 @@ ## ``newSocket()``. The difference is that the latter creates a new file ## descriptor. -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated import nativesockets, os, strutils, parseutils, times, sets, options export Port, `$`, `==` export Domain, SockType, Protocol diff --git a/lib/pure/os.nim b/lib/pure/os.nim index ddeee2c6b..11be8f0c1 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -10,7 +10,7 @@ ## This module contains basic operating system facilities like ## retrieving environment variables, reading command line arguments, ## working with directories, running shell commands, etc. -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated {.push debugger: off.} diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index 57387e62e..cecc94e92 100644 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -11,7 +11,7 @@ ## ## To unpack raw bytes look at the `streams `_ module. -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated {.push debugger:off .} # the user does not want to trace a part # of the standard library! diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim index 6ddd61afa..24ba012e5 100644 --- a/lib/pure/ropes.nim +++ b/lib/pure/ropes.nim @@ -19,7 +19,7 @@ include "system/inclrtl" import streams -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated {.push debugger:off .} # the user does not want to trace a part # of the standard library! diff --git a/lib/pure/strmisc.nim b/lib/pure/strmisc.nim index 89ef2fcd2..d1ff920c9 100644 --- a/lib/pure/strmisc.nim +++ b/lib/pure/strmisc.nim @@ -12,7 +12,7 @@ import strutils -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated proc expandTabs*(s: string, tabSize: int = 8): string {.noSideEffect, procvar.} = diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index 54fdcb4d0..849c16c34 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -17,7 +17,7 @@ import parseutils from math import pow, round, floor, log10 from algorithm import reverse -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated {.push debugger:off .} # the user does not want to trace a part # of the standard library! diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index 257c620f7..cc4d28f5b 100644 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -9,7 +9,7 @@ ## This module provides support to handle the Unicode UTF-8 encoding. -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated include "system/inclrtl" diff --git a/lib/system.nim b/lib/system.nim index 5e08dadc0..874b8c4d1 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -146,7 +146,7 @@ proc declared*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.} ## # missing it. when defined(useNimRtl): - {.deadCodeElim: on.} + {.deadCodeElim: on.} # dce option deprecated proc definedInScope*(x: untyped): bool {. magic: "DefinedInScope", noSideEffect, deprecated, compileTime.} diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index 62bc38da9..7e22f98c7 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -10,7 +10,7 @@ ## This module implements a small wrapper for some needed Win API procedures, ## so that the Nim compiler does not depend on the huge Windows module. -{.deadCodeElim:on.} +{.deadCodeElim: on.} # dce option deprecated import dynlib diff --git a/lib/wrappers/iup.nim b/lib/wrappers/iup.nim index d910173ca..dee2e14c7 100644 --- a/lib/wrappers/iup.nim +++ b/lib/wrappers/iup.nim @@ -34,7 +34,7 @@ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # **************************************************************************** -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated when defined(windows): const dllname = "iup(|30|27|26|25|24).dll" diff --git a/lib/wrappers/mysql.nim b/lib/wrappers/mysql.nim index 4464eae50..06c663822 100644 --- a/lib/wrappers/mysql.nim +++ b/lib/wrappers/mysql.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated {.push, callconv: cdecl.} when defined(Unix): diff --git a/lib/wrappers/odbcsql.nim b/lib/wrappers/odbcsql.nim index 1b2544ec0..43d1c504d 100644 --- a/lib/wrappers/odbcsql.nim +++ b/lib/wrappers/odbcsql.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated when not defined(ODBCVER): const diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim index 357343bff..86ae85369 100644 --- a/lib/wrappers/openssl.nim +++ b/lib/wrappers/openssl.nim @@ -22,7 +22,7 @@ ## ./bin/nim c -d:ssl -p:. -r tests/untestable/tssl.nim ## ./bin/nim c -d:ssl -p:. --dynlibOverride:ssl --passL:-lcrypto --passL:-lssl -r tests/untestable/tssl.nim -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated const useWinVersion = defined(Windows) or defined(nimdoc) diff --git a/lib/wrappers/pcre.nim b/lib/wrappers/pcre.nim index 6c7088bbf..e9e11960c 100644 --- a/lib/wrappers/pcre.nim +++ b/lib/wrappers/pcre.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated # The current PCRE version information. diff --git a/lib/wrappers/postgres.nim b/lib/wrappers/postgres.nim index f9a10dccb..7cb816f68 100644 --- a/lib/wrappers/postgres.nim +++ b/lib/wrappers/postgres.nim @@ -15,7 +15,7 @@ # connection-protocol. # -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated when defined(windows): const diff --git a/lib/wrappers/sqlite3.nim b/lib/wrappers/sqlite3.nim index a12945832..0276a0a65 100644 --- a/lib/wrappers/sqlite3.nim +++ b/lib/wrappers/sqlite3.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -{.deadCodeElim: on.} +{.deadCodeElim: on.} # dce option deprecated when defined(windows): when defined(nimOldDlls): const Lib = "sqlite3.dll" diff --git a/tests/enum/toptions.nim b/tests/enum/toptions.nim index e53acb2b3..da66f0067 100644 --- a/tests/enum/toptions.nim +++ b/tests/enum/toptions.nim @@ -4,7 +4,7 @@ type TOption = enum optNone, optForceFullMake, optBoehmGC, optRefcGC, optRangeCheck, optBoundsCheck, optOverflowCheck, optNilCheck, optAssert, optLineDir, - optWarns, optHints, optDeadCodeElim, optListCmd, optCompileOnly, + optWarns, optHints, optListCmd, optCompileOnly, optSafeCode, # only allow safe code optStyleCheck, optOptimizeSpeed, optOptimizeSize, optGenDynLib, optGenGuiApp, optStackTrace diff --git a/tests/iter/tobj_iter.nim b/tests/iter/tobj_iter.nim index eb0e37b23..a894755d7 100644 --- a/tests/iter/tobj_iter.nim +++ b/tests/iter/tobj_iter.nim @@ -4,8 +4,6 @@ discard """ # bug #2023 -{.deadCodeElim:on.} - type Obj = object iter: iterator (): int8 {.closure.} diff --git a/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim b/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim index 56d3edec4..f06c4e0be 100644 --- a/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim +++ b/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim @@ -23,7 +23,6 @@ const Lib = "libchipmunk.so.6.1.1" when defined(MoreNim): {.hint: "MoreNim defined; some Chipmunk functions replaced in Nim".} -{.deadCodeElim: on.} from math import sqrt, sin, cos, arctan2 when defined(CpUseFloat): {.hint: "CpUseFloat defined; using float32 as float".} diff --git a/tests/manyloc/keineschweine/dependencies/enet/enet.nim b/tests/manyloc/keineschweine/dependencies/enet/enet.nim index 3c4ce2017..3ea8172d5 100644 --- a/tests/manyloc/keineschweine/dependencies/enet/enet.nim +++ b/tests/manyloc/keineschweine/dependencies/enet/enet.nim @@ -20,7 +20,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. const Lib = "libenet.so.1(|.0.3)" -{.deadCodeElim: on.} const ENET_VERSION_MAJOR* = 1 ENET_VERSION_MINOR* = 3 diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim index d3a0c701d..86c12fbb0 100644 --- a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim +++ b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim @@ -1,5 +1,5 @@ import macros -{.deadCodeElim: on.} + #Inline macro.add() to allow for easier nesting proc und*(a: NimNode; b: NimNode): NimNode {.compileTime.} = a.add(b) diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim index 1524f0eb4..0060bf12b 100644 --- a/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim +++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim @@ -12,7 +12,7 @@ else: LibS = "libcsfml-system.so.2.0" LibW = "libcsfml-window.so.2.0" #{.error: "Platform unsupported".} -{.deadCodeElim: on.} + {.pragma: pf, pure, final.} type PClock* = ptr TClock diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim index 95a760e1f..b4eb1b8f0 100644 --- a/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim +++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim @@ -1,5 +1,5 @@ import sfml -{.deadCodeElim: on.} + let Black*: TColor = color(0, 0, 0) White*: TColor = color(255, 255, 255) diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim index 474d249aa..94c5308a9 100644 --- a/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim +++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim @@ -1,2 +1 @@ import sfml, math, strutils -{.deadCodeElim: on.} diff --git a/tests/manyloc/keineschweine/keineschweine.nim b/tests/manyloc/keineschweine/keineschweine.nim index c0f1bc031..59347ee46 100644 --- a/tests/manyloc/keineschweine/keineschweine.nim +++ b/tests/manyloc/keineschweine/keineschweine.nim @@ -5,7 +5,7 @@ import sg_gui, sg_assets, sound_buffer, enet_client when defined(profiler): import nimprof -{.deadCodeElim: on.} + type PPlayer* = ref TPlayer TPlayer* = object diff --git a/tests/manyloc/keineschweine/lib/sg_gui.nim b/tests/manyloc/keineschweine/lib/sg_gui.nim index ffc4e8215..b7448d9df 100644 --- a/tests/manyloc/keineschweine/lib/sg_gui.nim +++ b/tests/manyloc/keineschweine/lib/sg_gui.nim @@ -2,7 +2,7 @@ import sfml, sfml_colors, input_helpers, sg_packets from strutils import countlines -{.deadCodeElim: on.} + type PGuiContainer* = ref TGuiContainer TGuiContainer* = object of TObject diff --git a/tests/manyloc/keineschweine/server/nim.cfg b/tests/manyloc/keineschweine/server/nim.cfg index fdc45a8e1..211ad3003 100644 --- a/tests/manyloc/keineschweine/server/nim.cfg +++ b/tests/manyloc/keineschweine/server/nim.cfg @@ -1,5 +1,4 @@ debugger = off -deadCodeElim = on path = ".." path = "../genpacket" path = "../helpers" diff --git a/tests/manyloc/nake/nakefile.nim b/tests/manyloc/nake/nakefile.nim index 2055d7834..97af79a84 100644 --- a/tests/manyloc/nake/nakefile.nim +++ b/tests/manyloc/nake/nakefile.nim @@ -10,7 +10,7 @@ const ExeName = "keineschweine" ServerDefines = "-d:NoSFML -d:NoChipmunk" TestBuildDefines = "-d:escapeMenuTest -d:debugWeps -d:showFPS -d:moreNim -d:debugKeys -d:foo -d:recordMode --forceBuild" - ReleaseDefines = "-d:release --deadCodeElim:on" + ReleaseDefines = "-d:release" ReleaseTestDefines = "-d:debugWeps -d:debugKeys --forceBuild" task "testprofile", "..": diff --git a/tests/manyloc/standalone/barebone.nim.cfg b/tests/manyloc/standalone/barebone.nim.cfg index bb350ff55..b956bef8e 100644 --- a/tests/manyloc/standalone/barebone.nim.cfg +++ b/tests/manyloc/standalone/barebone.nim.cfg @@ -1,3 +1,2 @@ --os:standalone ---deadCodeElim:on --gc:none diff --git a/tests/pragmas/tnoreturn.nim b/tests/pragmas/tnoreturn.nim index 4d00c6034..bb59b1c71 100644 --- a/tests/pragmas/tnoreturn.nim +++ b/tests/pragmas/tnoreturn.nim @@ -2,13 +2,16 @@ discard """ ccodeCheck: "\\i @'__attribute__((noreturn))' .*" """ -proc noret1*(i: int) {.noreturn.} = +proc noret1*(i: int) {.noreturn.} = echo i -proc noret2*(i: int): void {.noreturn.} = +proc noret2*(i: int): void {.noreturn.} = echo i +noret1(1) +noret2(2) + var p {.used.}: proc(i: int): int doAssert(not compiles( p = proc(i: int): int {.noreturn.} = i # noreturn lambda returns int diff --git a/tests/rodfiles/deadg.nim b/tests/rodfiles/deadg.nim index 587608e14..0aee59bb8 100644 --- a/tests/rodfiles/deadg.nim +++ b/tests/rodfiles/deadg.nim @@ -1,6 +1,3 @@ - -{.deadCodeElim: on.} - proc p1*(x, y: int): int = result = x + y diff --git a/tools/nim.bash-completion b/tools/nim.bash-completion index 1c199a0cf..8e569079a 100644 --- a/tools/nim.bash-completion +++ b/tools/nim.bash-completion @@ -15,7 +15,7 @@ _nim() return 0 fi case $prev in - --stackTrace|--lineTrace|--threads|-x|--checks|--objChecks|--fieldChecks|--rangeChecks|--boundChecks|--overflowChecks|-a|--assertions|--floatChecks|--nanChecks|--infChecks|--deadCodeElim) + --stackTrace|--lineTrace|--threads|-x|--checks|--objChecks|--fieldChecks|--rangeChecks|--boundChecks|--overflowChecks|-a|--assertions|--floatChecks|--nanChecks|--infChecks) # Options that require on/off [[ "$cur" == "=" ]] && cur="" COMPREPLY=( $(compgen -W 'on off' -- "$cur") ) @@ -32,7 +32,7 @@ _nim() return 0 ;; *) - kw="-r -p= --path= -d= --define= -u= --undef= -f --forceBuild --opt= --app= --stackTrace= --lineTrace= --threads= -x= --checks= --objChecks= --fieldChecks= --rangeChecks= --boundChecks= --overflowChecks= -a= --assertions= --floatChecks= --nanChecks= --infChecks= --deadCodeElim=" + kw="-r -p= --path= -d= --define= -u= --undef= -f --forceBuild --opt= --app= --stackTrace= --lineTrace= --threads= -x= --checks= --objChecks= --fieldChecks= --rangeChecks= --boundChecks= --overflowChecks= -a= --assertions= --floatChecks= --nanChecks= --infChecks=" COMPREPLY=( $( compgen -W "${kw}" -- $cur ) ) _filedir '@(nim)' #$split diff --git a/tools/nim.zsh-completion b/tools/nim.zsh-completion index 57b5e163e..e9b9002fb 100644 --- a/tools/nim.zsh-completion +++ b/tools/nim.zsh-completion @@ -60,8 +60,6 @@ _nim() { '*--infChecks=off[turn Inf checks off]' \ '*--nilChecks=on[turn nil checks on]' \ '*--nilChecks=off[turn nil checks off]' \ - '*--deadCodeElim=on[whole program dead code elimination on]' \ - '*--deadCodeElim=off[whole program dead code elimination off]' \ '*--opt=none[do not optimize]' \ '*--opt=speed[optimize for speed|size - use -d:release for a release build]' \ '*--opt=size[optimize for size]' \ -- cgit 1.4.1-2-gfad0 From ee366f17469a96b418b58db17e03c892cf4f17d8 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Tue, 24 Apr 2018 09:34:20 +0200 Subject: .experimental can now be used to enable specific features --- changelog.md | 6 ++++ compiler/commands.nim | 39 ++++++++++++++++--------- compiler/nim.nim | 4 +-- compiler/options.nim | 14 +++++++-- compiler/pragmas.nim | 22 ++++++++++---- compiler/scriptconfig.nim | 6 ++-- compiler/semasgn.nim | 4 +-- compiler/semcall.nim | 2 +- compiler/semdata.nim | 6 ++-- compiler/semexprs.nim | 6 ++-- compiler/semstmts.nim | 71 +++++++++++++++------------------------------ compiler/semtypinst.nim | 4 +-- compiler/service.nim | 12 ++++---- compiler/transf.nim | 6 ++-- doc/advopt.txt | 5 ++-- doc/manual.rst | 21 +++++--------- nimsuggest/nimsuggest.nim | 8 ++--- tests/parallel/tparfind.nim | 2 +- 18 files changed, 122 insertions(+), 116 deletions(-) (limited to 'compiler/pragmas.nim') diff --git a/changelog.md b/changelog.md index a3332789a..8ac02a388 100644 --- a/changelog.md +++ b/changelog.md @@ -102,4 +102,10 @@ - Added ``macros.getProjectPath`` and ``ospaths.putEnv`` procs to Nim's virtual machine. +- The ``deadCodeElim`` option is now always turned on and the switch has no + effect anymore, but is recognized for backwards compatibility. + +- ``experimental`` is now a pragma / command line switch that can enable specific + language extensions, it is not an all-or-nothing switch anymore. + ### Bugfixes diff --git a/compiler/commands.nim b/compiler/commands.nim index 8d73ac90e..dc5d808ec 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -46,9 +46,9 @@ type passCmd2, # second pass over the command line passPP # preprocessor called processCommand() -proc processCommand*(switch: string, pass: TCmdLinePass) +proc processCommand*(switch: string, pass: TCmdLinePass; config: ConfigRef) proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; - config: ConfigRef = nil) + config: ConfigRef) # implementation @@ -58,7 +58,13 @@ const const Usage = slurp"../doc/basicopt.txt".replace("//", "") - AdvancedUsage = slurp"../doc/advopt.txt".replace("//", "") + FeatureDesc = block: + var x = "" + for f in low(Feature)..high(Feature): + if x.len > 0: x.add "|" + x.add $f + x + AdvancedUsage = slurp"../doc/advopt.txt".replace("//", "") % FeatureDesc proc getCommandLineDesc(): string = result = (HelpMessage % [VersionAsString, platform.OS[platform.hostOS].name, @@ -276,7 +282,6 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool = of "tlsemulation": result = contains(gGlobalOptions, optTlsEmulation) of "implicitstatic": result = contains(gOptions, optImplicitStatic) of "patterns": result = contains(gOptions, optPatterns) - of "experimental": result = gExperimentalMode of "excessivestacktrace": result = contains(gGlobalOptions, optExcessiveStackTrace) else: invalidCmdLineOption(passCmd1, switch, info) @@ -339,7 +344,7 @@ proc dynlibOverride(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = options.inclDynlibOverride(arg) proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; - config: ConfigRef = nil) = + config: ConfigRef) = var theOS: TSystemOS cpu: TSystemCPU @@ -694,8 +699,13 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; # only supported for compatibility. Does nothing. expectArg(switch, arg, pass, info) of "experimental": - expectNoArg(switch, arg, pass, info) - gExperimentalMode = true + if arg.len == 0: + config.features.incl oldExperimentalFeatures + else: + try: + config.features.incl parseEnum[Feature](arg) + except ValueError: + localError(info, "unknown experimental feature") of "nocppexceptions": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optNoCppExceptions) @@ -706,7 +716,8 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; config.cppDefine(arg) of "newruntime": expectNoArg(switch, arg, pass, info) - newDestructors = true + doAssert(config != nil) + incl(config.features, destructor) defineSymbol("nimNewRuntime") of "cppcompiletonamespace": expectNoArg(switch, arg, pass, info) @@ -716,10 +727,10 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg) else: invalidCmdLineOption(pass, switch, info) -proc processCommand(switch: string, pass: TCmdLinePass) = +proc processCommand(switch: string, pass: TCmdLinePass; config: ConfigRef) = var cmd, arg: string splitSwitch(switch, cmd, arg, pass, gCmdLineInfo) - processSwitch(cmd, arg, pass, gCmdLineInfo) + processSwitch(cmd, arg, pass, gCmdLineInfo, config) var @@ -727,19 +738,19 @@ var # the arguments to be passed to the program that # should be run -proc processSwitch*(pass: TCmdLinePass; p: OptParser) = +proc processSwitch*(pass: TCmdLinePass; p: OptParser; config: ConfigRef) = # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off") # we fix this here var bracketLe = strutils.find(p.key, '[') if bracketLe >= 0: var key = substr(p.key, 0, bracketLe - 1) var val = substr(p.key, bracketLe + 1) & ':' & p.val - processSwitch(key, val, pass, gCmdLineInfo) + processSwitch(key, val, pass, gCmdLineInfo, config) else: - processSwitch(p.key, p.val, pass, gCmdLineInfo) + processSwitch(p.key, p.val, pass, gCmdLineInfo, config) proc processArgument*(pass: TCmdLinePass; p: OptParser; - argsCount: var int): bool = + argsCount: var int; config: ConfigRef): bool = if argsCount == 0: # nim filename.nims is the same as "nim e filename.nims": if p.key.endswith(".nims"): diff --git a/compiler/nim.nim b/compiler/nim.nim index 8f3463be9..3fa733303 100644 --- a/compiler/nim.nim +++ b/compiler/nim.nim @@ -42,7 +42,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) = writeCommandLineUsage() else: # Process command line arguments: - processCmdLine(passCmd1, "") + processCmdLine(passCmd1, "", config) if gProjectName == "-": gProjectName = "stdinfile" gProjectFull = "stdinfile" @@ -71,7 +71,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) = # now process command line arguments again, because some options in the # command line can overwite the config file's settings extccomp.initVars() - processCmdLine(passCmd2, "") + processCmdLine(passCmd2, "", config) if options.command == "": rawMessage(errNoCommand, command) mainCommand(newModuleGraph(config), cache) diff --git a/compiler/options.nim b/compiler/options.nim index 7126d4398..24c9d0f73 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -103,13 +103,23 @@ type ideNone, ideSug, ideCon, ideDef, ideUse, ideDus, ideChk, ideMod, ideHighlight, ideOutline, ideKnown, ideMsg + Feature* = enum ## experimental features + implicitDeref, + dotOperators, + callOperator, + parallel, + destructor + ConfigRef* = ref object ## eventually all global configuration should be moved here cppDefines*: HashSet[string] headerFile*: string + features*: set[Feature] + +const oldExperimentalFeatures* = {implicitDeref, dotOperators, callOperator, parallel} proc newConfigRef*(): ConfigRef = result = ConfigRef(cppDefines: initSet[string](), - headerFile: "") + headerFile: "", features: {}) proc cppDefine*(c: ConfigRef; define: string) = c.cppDefines.incl define @@ -146,8 +156,6 @@ var gListFullPaths*: bool gPreciseStack*: bool = false gNoNimblePath* = false - gExperimentalMode*: bool - newDestructors*: bool gDynlibOverrideAll*: bool useNimNamespace*: bool diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 9e9233fe7..5aa903771 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -680,6 +680,22 @@ proc semCustomPragma(c: PContext, n: PNode): PNode = elif n.kind == nkExprColonExpr: result.kind = n.kind # pragma(arg) -> pragma: arg +proc processExperimental(c: PContext; n: PNode; s: PSym) = + if not isTopLevel(c): + localError(n.info, "'experimental' pragma only valid as toplevel statement") + if n.kind notin nkPragmaCallKinds or n.len != 2: + c.features.incl oldExperimentalFeatures + else: + n[1] = c.semConstExpr(c, n[1]) + case n[1].kind + of nkStrLit, nkRStrLit, nkTripleStrLit: + try: + c.features.incl parseEnum[Feature](n[1].strVal) + except ValueError: + localError(n[1].info, "unknown experimental feature") + else: + localError(n.info, errStringLiteralExpected) + proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, validPragmas: TSpecialWords): bool = var it = n.sons[i] @@ -993,11 +1009,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, else: it.sons[1] = c.semExpr(c, it.sons[1]) of wExperimental: - noVal(it) - if isTopLevel(c): - c.module.flags.incl sfExperimental - else: - localError(it.info, "'experimental' pragma only valid as toplevel statement") + processExperimental(c, it, sym) of wThis: if it.kind in nkPragmaCallKinds and it.len == 2: c.selfName = considerQuotedIdent(it[1]) diff --git a/compiler/scriptconfig.nim b/compiler/scriptconfig.nim index 692a8d896..c533f4cb4 100644 --- a/compiler/scriptconfig.nim +++ b/compiler/scriptconfig.nim @@ -26,7 +26,7 @@ proc listDirs(a: VmArgs, filter: set[PathComponent]) = setResult(a, result) proc setupVM*(module: PSym; cache: IdentCache; scriptName: string; - config: ConfigRef = nil): PEvalContext = + config: ConfigRef): PEvalContext = # For Nimble we need to export 'setupVM'. result = newCtx(module, cache) result.mode = emRepl @@ -128,7 +128,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string; cbconf getCommand: setResult(a, options.command) cbconf switch: - processSwitch(a.getString 0, a.getString 1, passPP, module.info) + processSwitch(a.getString 0, a.getString 1, passPP, module.info, config) cbconf hintImpl: processSpecificNote(a.getString 0, wHint, passPP, module.info, a.getString 1) @@ -150,7 +150,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string; options.cppDefine(config, a.getString(0)) proc runNimScript*(cache: IdentCache; scriptName: string; - freshDefines=true; config: ConfigRef=nil) = + freshDefines=true; config: ConfigRef) = rawMessage(hintConf, scriptName) passes.gIncludeFile = includeModule passes.gImportModule = importModule diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim index bbd2baf6e..5c7b91f6d 100644 --- a/compiler/semasgn.nim +++ b/compiler/semasgn.nim @@ -101,7 +101,7 @@ proc newOpCall(op: PSym; x: PNode): PNode = proc destructorCall(c: PContext; op: PSym; x: PNode): PNode = result = newNodeIT(nkCall, x.info, op.typ.sons[0]) result.add(newSymNode(op)) - if newDestructors: + if destructor in c.features: result.add genAddr(c, x) else: result.add x @@ -319,7 +319,7 @@ proc liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) = ## In the semantic pass this is called in strategic places ## to ensure we lift assignment, destructors and moves properly. ## The later 'destroyer' pass depends on it. - if not newDestructors or not hasDestructor(typ): return + if destructor notin c.features or not hasDestructor(typ): return when false: # do not produce wrong liftings while we're still instantiating generics: # now disabled; breaks topttree.nim! diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 0fc12f164..f443339f5 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -434,7 +434,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode, "Non-matching candidates for " & renderTree(n) & "\n" & candidates) result = semResolvedCall(c, n, r) - elif experimentalMode(c) and canDeref(n): + elif implicitDeref in c.features and canDeref(n): # try to deref the first argument and then try overloading resolution again: # # XXX: why is this here? diff --git a/compiler/semdata.nim b/compiler/semdata.nim index bcc1bba15..8159abf8f 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -130,6 +130,7 @@ type signatures*: TStrTable recursiveDep*: string suggestionsMade*: bool + features*: set[Feature] inTypeContext*: int typesWithOps*: seq[(PType, PType)] #\ # We need to instantiate the type bound ops lazily after @@ -225,7 +226,7 @@ proc newContext*(graph: ModuleGraph; module: PSym; cache: IdentCache): PContext result.graph = graph initStrTable(result.signatures) result.typesWithOps = @[] - + result.features = graph.config.features proc inclSym(sq: var TSymSeq, s: PSym) = var L = len(sq) @@ -398,6 +399,3 @@ proc checkMinSonsLen*(n: PNode, length: int) = proc isTopLevel*(c: PContext): bool {.inline.} = result = c.currentScope.depthLevel <= 2 - -proc experimentalMode*(c: PContext): bool {.inline.} = - result = gExperimentalMode or sfExperimental in c.module.flags diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 279b6cc57..6ad5d931d 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -663,7 +663,7 @@ proc resolveIndirectCall(c: PContext; n, nOrig: PNode; matches(c, n, nOrig, result) if result.state != csMatch: # try to deref the first argument: - if experimentalMode(c) and canDeref(n): + if implicitDeref in c.features and canDeref(n): n.sons[1] = n.sons[1].tryDeref initCandidate(c, result, t) matches(c, n, nOrig, result) @@ -1452,7 +1452,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode = typeMismatch(n.info, lhs.typ, rhsTyp) n.sons[1] = fitNode(c, le, rhs, n.info) - if not newDestructors: + if destructor notin c.features: if tfHasAsgn in lhs.typ.flags and not lhsIsResult and mode != noOverloadedAsgn: return overloadedAsgn(c, lhs, n.sons[1]) @@ -1884,7 +1884,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = result = newStrNodeT(renderTree(n[1], {renderNoComments}), n) result.typ = getSysType(tyString) of mParallel: - if not experimentalMode(c): + if parallel notin c.features: localError(n.info, "use the {.experimental.} pragma to enable 'parallel'") result = setMs(n, s) var x = n.lastSon diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 8d7747fb4..94090852f 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -385,30 +385,9 @@ proc checkNilable(v: PSym) = include semasgn proc addToVarSection(c: PContext; result: var PNode; orig, identDefs: PNode) = - # consider this: - # var - # x = 0 - # withOverloadedAssignment = foo() - # y = use(withOverloadedAssignment) - # We need to split this into a statement list with multiple 'var' sections - # in order for this transformation to be correct. let L = identDefs.len let value = identDefs[L-1] - if value.typ != nil and tfHasAsgn in value.typ.flags and not newDestructors: - # the spec says we need to rewrite 'var x = T()' to 'var x: T; x = T()': - identDefs.sons[L-1] = emptyNode - if result.kind != nkStmtList: - let oldResult = result - oldResult.add identDefs - result = newNodeI(nkStmtList, result.info) - result.add oldResult - else: - let o = copyNode(orig) - o.add identDefs - result.add o - for i in 0 .. L-3: - result.add overloadedAsgn(c, identDefs[i], value) - elif result.kind == nkStmtList: + if result.kind == nkStmtList: let o = copyNode(orig) o.add identDefs result.add o @@ -1267,9 +1246,6 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = gp = newNodeI(nkGenericParams, n.info) if n.sons[paramsPos].kind != nkEmpty: - #if n.kind == nkDo and not experimentalMode(c): - # localError(n.sons[paramsPos].info, - # "use the {.experimental.} pragma to enable 'do' with parameters") semParamList(c, n.sons[paramsPos], gp, s) # paramsTypeCheck(c, s.typ) if sonsLen(gp) > 0 and n.sons[genericParamsPos].kind == nkEmpty: @@ -1363,27 +1339,26 @@ proc maybeAddResult(c: PContext, s: PSym, n: PNode) = proc semOverride(c: PContext, s: PSym, n: PNode) = case s.name.s.normalize - of "destroy", "=destroy": - if newDestructors: - let t = s.typ - var noError = false - if t.len == 2 and t.sons[0] == nil and t.sons[1].kind == tyVar: - var obj = t.sons[1].sons[0] - while true: - incl(obj.flags, tfHasAsgn) - if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.lastSon - elif obj.kind == tyGenericInvocation: obj = obj.sons[0] - else: break - if obj.kind in {tyObject, tyDistinct}: - if obj.destructor.isNil: - obj.destructor = s - else: - localError(n.info, errGenerated, - "cannot bind another '" & s.name.s & "' to: " & typeToString(obj)) - noError = true - if not noError and sfSystemModule notin s.owner.flags: - localError(n.info, errGenerated, - "signature for '" & s.name.s & "' must be proc[T: object](x: var T)") + of "=destroy": + let t = s.typ + var noError = false + if t.len == 2 and t.sons[0] == nil and t.sons[1].kind == tyVar: + var obj = t.sons[1].sons[0] + while true: + incl(obj.flags, tfHasAsgn) + if obj.kind in {tyGenericBody, tyGenericInst}: obj = obj.lastSon + elif obj.kind == tyGenericInvocation: obj = obj.sons[0] + else: break + if obj.kind in {tyObject, tyDistinct}: + if obj.destructor.isNil: + obj.destructor = s + else: + localError(n.info, errGenerated, + "cannot bind another '" & s.name.s & "' to: " & typeToString(obj)) + noError = true + if not noError and sfSystemModule notin s.owner.flags: + localError(n.info, errGenerated, + "signature for '" & s.name.s & "' must be proc[T: object](x: var T)") incl(s.flags, sfUsed) of "deepcopy", "=deepcopy": if s.typ.len == 2 and @@ -1612,9 +1587,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, s.options = gOptions if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n) if s.name.s[0] in {'.', '('}: - if s.name.s in [".", ".()", ".="] and not experimentalMode(c) and not newDestructors: + if s.name.s in [".", ".()", ".="] and {destructor, dotOperators} * c.features == {}: message(n.info, warnDeprecated, "overloaded '.' and '()' operators are now .experimental; " & s.name.s) - elif s.name.s == "()" and not experimentalMode(c): + elif s.name.s == "()" and callOperator notin c.features: message(n.info, warnDeprecated, "overloaded '()' operators are now .experimental; " & s.name.s) if n.sons[bodyPos].kind != nkEmpty: diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 09434c925..c97c1186e 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -368,7 +368,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = assert newbody.kind in {tyRef, tyPtr} assert newbody.lastSon.typeInst == nil newbody.lastSon.typeInst = result - if newDestructors: + if destructor in cl.c.features: cl.c.typesWithOps.add((newbody, result)) else: typeBound(cl.c, newbody, result, assignment, cl.info) @@ -545,7 +545,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = else: discard proc instAllTypeBoundOp*(c: PContext, info: TLineInfo) = - if not newDestructors: return + if destructor notin c.features: return var i = 0 while i < c.typesWithOps.len: let (newty, oldty) = c.typesWithOps[i] diff --git a/compiler/service.nim b/compiler/service.nim index ac04b7860..7cdfc112c 100644 --- a/compiler/service.nim +++ b/compiler/service.nim @@ -26,7 +26,7 @@ var # in caas mode, the list of defines and options will be given at start-up? # it's enough to check that the previous compilation command is the same? -proc processCmdLine*(pass: TCmdLinePass, cmd: string) = +proc processCmdLine*(pass: TCmdLinePass, cmd: string; config: ConfigRef) = var p = parseopt.initOptParser(cmd) var argsCount = 0 while true: @@ -36,19 +36,19 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) = of cmdLongoption, cmdShortOption: if p.key == " ": p.key = "-" - if processArgument(pass, p, argsCount): break + if processArgument(pass, p, argsCount, config): break else: - processSwitch(pass, p) + processSwitch(pass, p, config) of cmdArgument: - if processArgument(pass, p, argsCount): break + if processArgument(pass, p, argsCount, config): break if pass == passCmd2: if optRun notin gGlobalOptions and arguments != "" and options.command.normalize != "run": rawMessage(errArgsNeedRunOption, []) -proc serve*(cache: IdentCache; action: proc (cache: IdentCache){.nimcall.}) = +proc serve*(cache: IdentCache; action: proc (cache: IdentCache){.nimcall.}; config: ConfigRef) = template execute(cmd) = curCaasCmd = cmd - processCmdLine(passCmd2, cmd) + processCmdLine(passCmd2, cmd, config) action(cache) gErrorCounter = 0 diff --git a/compiler/transf.nim b/compiler/transf.nim index f30f8583a..f7ec6c97f 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -979,7 +979,7 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode = #result = liftLambdas(prc, result) when useEffectSystem: trackProc(prc, result) result = liftLocalsIfRequested(prc, result) - if c.needsDestroyPass and newDestructors: + if c.needsDestroyPass: #and newDestructors: result = injectDestructorCalls(prc, result) incl(result.flags, nfTransf) #if prc.name.s == "testbody": @@ -996,7 +996,7 @@ proc transformStmt*(module: PSym, n: PNode): PNode = when useEffectSystem: trackTopLevelStmt(module, result) #if n.info ?? "temp.nim": # echo renderTree(result, {renderIds}) - if c.needsDestroyPass and newDestructors: + if c.needsDestroyPass: result = injectDestructorCalls(module, result) incl(result.flags, nfTransf) @@ -1007,6 +1007,6 @@ proc transformExpr*(module: PSym, n: PNode): PNode = var c = openTransf(module, "") result = processTransf(c, n, module) liftDefer(c, result) - if c.needsDestroyPass and newDestructors: + if c.needsDestroyPass: result = injectDestructorCalls(module, result) incl(result.flags, nfTransf) diff --git a/doc/advopt.txt b/doc/advopt.txt index bf7dd7fb4..0d1578f78 100644 --- a/doc/advopt.txt +++ b/doc/advopt.txt @@ -35,7 +35,7 @@ Advanced options: --noLinking compile Nim and generated files but do not link --noMain do not generate a main procedure --genScript generate a compile script (in the 'nimcache' - subdirectory named 'compile_$project$scriptext') + subdirectory named 'compile_$$project$$scriptext') --genDeps generate a '.deps' file containing the dependencies --os:SYMBOL set the target operating system (cross-compilation) --cpu:SYMBOL set the target processor (cross-compilation) @@ -88,5 +88,6 @@ Advanced options: --parallelBuild:0|1|... perform a parallel build value = number of processors (0 for auto-detect) --verbosity:0|1|2|3 set Nim's verbosity level (1 is default) - --experimental enable experimental language features + --experimental:$1 + enable experimental language feature -v, --version show detailed version information diff --git a/doc/manual.rst b/doc/manual.rst index f1330d524..636bf796b 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -1397,10 +1397,10 @@ dereferencing operations for reference types: Automatic dereferencing is also performed for the first argument of a routine call. But currently this feature has to be only enabled -via ``{.experimental.}``: +via ``{.experimental: "implicitDeref".}``: .. code-block:: nim - {.experimental.} + {.experimental: "implicitDeref".} proc depth(x: NodeObj): int = ... @@ -5588,7 +5588,7 @@ dot operators ------------- **Note**: Dot operators are still experimental and so need to be enabled -via ``{.experimental.}``. +via ``{.experimental: "dotOperators".}``. Nim offers a special family of dot operators that can be used to intercept and rewrite proc call and field access attempts, referring @@ -6885,17 +6885,12 @@ is uncertain (it may be removed any time). Example: .. code-block:: nim - {.experimental.} - type - FooId = distinct int - BarId = distinct int - using - foo: FooId - bar: BarId + {.experimental: "parallel".} proc useUsing(bar, foo) = - echo "bar is of type BarId" - echo "foo is of type FooId" + parallel: + for i in 0..4: + echo "echo in parallel" Implementation Specific Pragmas @@ -7917,7 +7912,7 @@ Example: # Compute PI in an inefficient way import strutils, math, threadpool - {.experimental.} + {.experimental: "parallel".} proc term(k: float): float = 4 * math.pow(-1, k) / (2*k + 1) diff --git a/nimsuggest/nimsuggest.nim b/nimsuggest/nimsuggest.nim index 49e61b9a9..b2764e9ee 100644 --- a/nimsuggest/nimsuggest.nim +++ b/nimsuggest/nimsuggest.nim @@ -518,7 +518,7 @@ proc mainCommand(graph: ModuleGraph; cache: IdentCache) = close(requests) close(results) -proc processCmdLine*(pass: TCmdLinePass, cmd: string) = +proc processCmdLine*(pass: TCmdLinePass, cmd: string; config: ConfigRef) = var p = parseopt.initOptParser(cmd) while true: parseopt.next(p) @@ -562,7 +562,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) = gRefresh = true of "maxresults": suggestMaxResults = parseInt(p.val) - else: processSwitch(pass, p) + else: processSwitch(pass, p, config) of cmdArgument: let a = unixToNativePath(p.key) if dirExists(a) and not fileExists(a.addFileExt("nim")): @@ -577,7 +577,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) = if paramCount() == 0: stdout.writeline(Usage) else: - processCmdLine(passCmd1, "") + processCmdLine(passCmd1, "", config) if gMode != mstdin: msgs.writelnHook = proc (msg: string) = discard if gProjectName != "": @@ -616,7 +616,7 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) = runNimScript(cache, gProjectPath / "config.nims", freshDefines=false, config) extccomp.initVars() - processCmdLine(passCmd2, "") + processCmdLine(passCmd2, "", config) let graph = newModuleGraph(config) graph.suggestMode = true diff --git a/tests/parallel/tparfind.nim b/tests/parallel/tparfind.nim index 9de5012f5..4b3610c67 100644 --- a/tests/parallel/tparfind.nim +++ b/tests/parallel/tparfind.nim @@ -4,7 +4,7 @@ discard """ import threadpool, sequtils -{.experimental.} +{.experimental: "parallel".} proc linearFind(a: openArray[int]; x, offset: int): int = for i, y in a: -- cgit 1.4.1-2-gfad0 From ae5c946a325c8833472173e63017dbed39f23abe Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Sun, 29 Apr 2018 13:50:21 +0300 Subject: Support thread-local variables declared inside procs; fixes #7565 --- changelog.md | 3 ++ compiler/pragmas.nim | 2 +- doc/manual.rst | 5 +-- tests/threads/tthreadvars.nim | 78 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 tests/threads/tthreadvars.nim (limited to 'compiler/pragmas.nim') diff --git a/changelog.md b/changelog.md index fe935106a..4f87d5fe1 100644 --- a/changelog.md +++ b/changelog.md @@ -103,6 +103,9 @@ - The command syntax now supports keyword arguments after the first comma. +- Thread-local variables can now be declared inside procs. This implies all + the effects of the `global` pragma. + ### Tool changes - ``jsondoc2`` has been renamed ``jsondoc``, similar to how ``doc2`` was renamed diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 5aa903771..0b8bcd374 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -777,7 +777,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, incl(sym.flags, sfRegister) of wThreadVar: noVal(it) - incl(sym.flags, sfThread) + incl(sym.flags, {sfThread, sfGlobal}) of wDeadCodeElimUnused: discard # deprecated, dead code elim always on of wNoForward: pragmaNoForward(c, it) of wReorder: pragmaNoForward(c, it, sfReorder) diff --git a/doc/manual.rst b/doc/manual.rst index fabcf058a..1a4ed19b7 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -7798,8 +7798,9 @@ Future directions: Threadvar pragma ---------------- -A global variable can be marked with the ``threadvar`` pragma; it is -a `thread-local`:idx: variable then: +A variable can be marked with the ``threadvar`` pragma, which makes it a +`thread-local`:idx: variable; Additionally, this implies all the effects +of the ``global`` pragma. .. code-block:: nim var checkpoints* {.threadvar.}: seq[string] diff --git a/tests/threads/tthreadvars.nim b/tests/threads/tthreadvars.nim new file mode 100644 index 000000000..81aa2e5ec --- /dev/null +++ b/tests/threads/tthreadvars.nim @@ -0,0 +1,78 @@ +discard """ +output: ''' +10 +1111 +1222 +3030303 +3060606 +6060606 +6121212 +3030903 +3061206 +3031503 +3061806 +5050505 +5101010 +''' +""" + +import typetraits + +var tls1 {.threadvar.}: int +var g0: int +var g1 {.global.}: int + +proc customInc(x: var int, delta: int) = + x += delta + +customInc(tls1, 10) +echo tls1 + +proc nonGenericProc: int = + var local: int + var nonGenericTls {.threadvar.}: int + var nonGenericGlobal {.global.}: int + var nonGenericMixedPragmas {.global, threadvar.}: int + + customInc local, 1000 + customInc nonGenericTls, 1 + customInc nonGenericGlobal, 10 + customInc nonGenericMixedPragmas, 100 + + return local + nonGenericTls + nonGenericGlobal + nonGenericMixedPragmas + +proc genericProc(T: typedesc): int = + var local: int + var genericTls {.threadvar.}: int + var genericGlobal {.global.}: int + var genericMixedPragmas {.global, threadvar.}: int + + customInc local, T.name.len * 1000000 + customInc genericTls, T.name.len * 1 + customInc genericGlobal, T.name.len * 100 + customInc genericMixedPragmas, T.name.len * 10000 + + return local + genericTls + genericGlobal + genericMixedPragmas + +echo nonGenericProc() +echo nonGenericProc() + +echo genericProc(int) +echo genericProc(int) + +echo genericProc(string) +echo genericProc(string) + +proc echoInThread[T]() {.thread.} = + echo genericProc(T) + echo genericProc(T) + +proc newEchoThread(T: typedesc) = + var t: Thread[void] + createThread(t, echoInThread[T]) + joinThreads(t) + +newEchoThread int +newEchoThread int +newEchoThread float + -- cgit 1.4.1-2-gfad0 From bb8c47b496131a64aa9fa25ac4d538807397b102 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 11 May 2018 18:53:18 +0200 Subject: pragmas compiles again --- compiler/cgmeth.nim | 45 ++--- compiler/configuration.nim | 4 +- compiler/importer.nim | 34 ++-- compiler/pragmas.nim | 444 +++++++++++++++++++++++---------------------- compiler/procfind.nim | 14 +- 5 files changed, 272 insertions(+), 269 deletions(-) (limited to 'compiler/pragmas.nim') diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim index 0513e88f4..1d72952e2 100644 --- a/compiler/cgmeth.nim +++ b/compiler/cgmeth.nim @@ -11,9 +11,9 @@ import intsets, options, ast, astalgo, msgs, idents, renderer, types, magicsys, - sempass2, strutils, modulegraphs + sempass2, strutils, modulegraphs, configuration -proc genConv(n: PNode, d: PType, downcast: bool): PNode = +proc genConv(n: PNode, d: PType, downcast: bool; conf: ConfigRef): PNode = var dest = skipTypes(d, abstractPtrs) var source = skipTypes(n.typ, abstractPtrs) if (source.kind == tyObject) and (dest.kind == tyObject): @@ -24,12 +24,12 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode = elif diff < 0: result = newNodeIT(nkObjUpConv, n.info, d) addSon(result, n) - if downcast: internalError(n.info, "cgmeth.genConv: no upcast allowed") + if downcast: internalError(conf, n.info, "cgmeth.genConv: no upcast allowed") elif diff > 0: result = newNodeIT(nkObjDownConv, n.info, d) addSon(result, n) if not downcast: - internalError(n.info, "cgmeth.genConv: no downcast allowed") + internalError(conf, n.info, "cgmeth.genConv: no downcast allowed") else: result = n else: @@ -42,7 +42,7 @@ proc getDispatcher*(s: PSym): PSym = let disp = dispn.sym if sfDispatcher in disp.flags: result = disp -proc methodCall*(n: PNode): PNode = +proc methodCall*(n: PNode; conf: ConfigRef): PNode = result = n # replace ordinary method by dispatcher method: let disp = getDispatcher(result.sons[0].sym) @@ -50,9 +50,9 @@ proc methodCall*(n: PNode): PNode = result.sons[0].sym = disp # change the arguments to up/downcasts to fit the dispatcher's parameters: for i in countup(1, sonsLen(result)-1): - result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true) + result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true, conf) else: - localError(n.info, "'" & $result.sons[0] & "' lacks a dispatcher") + localError(conf, n.info, "'" & $result.sons[0] & "' lacks a dispatcher") type MethodResult = enum No, Invalid, Yes @@ -130,7 +130,7 @@ proc createDispatcher(s: PSym): PSym = attachDispatcher(disp, newSymNode(disp)) return disp -proc fixupDispatcher(meth, disp: PSym) = +proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) = # We may have constructed the dispatcher from a method prototype # and need to augment the incomplete dispatcher with information # from later definitions, particularly the resultPos slot. Also, @@ -149,7 +149,7 @@ proc fixupDispatcher(meth, disp: PSym) = disp.typ.lockLevel = meth.typ.lockLevel elif meth.typ.lockLevel != UnspecifiedLockLevel and meth.typ.lockLevel != disp.typ.lockLevel: - message(meth.info, warnLockLevel, + message(conf, meth.info, warnLockLevel, "method has lock level $1, but another method has $2" % [$meth.typ.lockLevel, $disp.typ.lockLevel]) # XXX The following code silences a duplicate warning in @@ -166,13 +166,13 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) = of Yes: add(g.methods[i].methods, s) attachDispatcher(s, lastSon(disp.ast)) - fixupDispatcher(s, disp) + fixupDispatcher(s, disp, g.config) #echo "fixup ", disp.name.s, " ", disp.id - when useEffectSystem: checkMethodEffects(disp, s) + when useEffectSystem: checkMethodEffects(g, disp, s) if {sfBase, sfFromGeneric} * s.flags == {sfBase} and g.methods[i].methods[0] != s: # already exists due to forwarding definition? - localError(s.info, "method is not a base") + localError(g.config, s.info, "method is not a base") return of No: discard of Invalid: @@ -183,10 +183,10 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) = #if fromCache: # internalError(s.info, "no method dispatcher found") if witness != nil: - localError(s.info, "invalid declaration order; cannot attach '" & s.name.s & + localError(g.config, s.info, "invalid declaration order; cannot attach '" & s.name.s & "' to method defined here: " & $witness.info) elif sfBase notin s.flags: - message(s.info, warnUseBase) + message(g.config, s.info, warnUseBase) proc relevantCol(methods: TSymSeq, col: int): bool = # returns true iff the position is relevant @@ -225,32 +225,33 @@ proc sortBucket(a: var TSymSeq, relevantCols: IntSet) = a[j] = v if h == 1: break -proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym = +proc genDispatcher(g: ModuleGraph; methods: TSymSeq, relevantCols: IntSet): PSym = var base = lastSon(methods[0].ast).sym result = base var paramLen = sonsLen(base.typ) var nilchecks = newNodeI(nkStmtList, base.info) var disp = newNodeI(nkIfStmt, base.info) - var ands = getSysSym("and") - var iss = getSysSym("of") + var ands = getSysSym(g, unknownLineInfo(), "and") + var iss = getSysSym(g, unknownLineInfo(), "of") + let boolType = getSysType(g, unknownLineInfo(), tyBool) for col in countup(1, paramLen - 1): if contains(relevantCols, col): let param = base.typ.n.sons[col].sym if param.typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}: addSon(nilchecks, newTree(nkCall, - newSymNode(getCompilerProc"chckNilDisp"), newSymNode(param))) + newSymNode(getCompilerProc(g, "chckNilDisp")), newSymNode(param))) for meth in countup(0, high(methods)): var curr = methods[meth] # generate condition: var cond: PNode = nil for col in countup(1, paramLen - 1): if contains(relevantCols, col): - var isn = newNodeIT(nkCall, base.info, getSysType(tyBool)) + var isn = newNodeIT(nkCall, base.info, boolType) addSon(isn, newSymNode(iss)) let param = base.typ.n.sons[col].sym addSon(isn, newSymNode(param)) addSon(isn, newNodeIT(nkType, base.info, curr.typ.sons[col])) if cond != nil: - var a = newNodeIT(nkCall, base.info, getSysType(tyBool)) + var a = newNodeIT(nkCall, base.info, boolType) addSon(a, newSymNode(ands)) addSon(a, cond) addSon(a, isn) @@ -262,7 +263,7 @@ proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym = addSon(call, newSymNode(curr)) for col in countup(1, paramLen - 1): addSon(call, genConv(newSymNode(base.typ.n.sons[col].sym), - curr.typ.sons[col], false)) + curr.typ.sons[col], false, g.config)) var ret: PNode if retTyp != nil: var a = newNodeI(nkFastAsgn, base.info) @@ -290,4 +291,4 @@ proc generateMethodDispatchers*(g: ModuleGraph): PNode = if relevantCol(g.methods[bucket].methods, col): incl(relevantCols, col) sortBucket(g.methods[bucket].methods, relevantCols) addSon(result, - newSymNode(genDispatcher(g.methods[bucket].methods, relevantCols))) + newSymNode(genDispatcher(g, g.methods[bucket].methods, relevantCols))) diff --git a/compiler/configuration.nim b/compiler/configuration.nim index 44345186d..b2548eb74 100644 --- a/compiler/configuration.nim +++ b/compiler/configuration.nim @@ -221,7 +221,7 @@ errUseQualifier: "ambiguous identifier: '$1' -- use a qualifier", errTypeExpected: "type expected", errSystemNeeds: "system module needs '$1'", errExecutionOfProgramFailed: "execution of an external program failed: '$1'", -errNotOverloadable: "overloaded '$1' leads to ambiguous calls", +errNotOverloadable: , errInvalidArgForX: "invalid argument for '$1'", errStmtHasNoEffect: "statement has no effect", errXExpectsTypeOrValue: "'$1' expects a type or value", @@ -305,7 +305,7 @@ errInvalidOrderInEnumX: "invalid order in enum '$1'", errEnumXHasHoles: "enum '$1' has holes", errExceptExpected: "'except' or 'finally' expected", errInvalidTry: "after catch all 'except' or 'finally' no section may follow", -errOptionExpected: "option expected, but found '$1'", +errOptionExpected: , errXisNoLabel: "'$1' is not a label", errNotAllCasesCovered: "not all cases are covered", errUnknownSubstitionVar: "unknown substitution variable: '$1'", diff --git a/compiler/importer.nim b/compiler/importer.nim index f4903e6c4..05beb1d98 100644 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -11,7 +11,7 @@ import intsets, strutils, os, ast, astalgo, msgs, options, idents, rodread, lookups, - semdata, passes, renderer, modulepaths, sigmatch + semdata, passes, renderer, modulepaths, sigmatch, configuration proc evalImport*(c: PContext, n: PNode): PNode proc evalFrom*(c: PContext, n: PNode): PNode @@ -40,7 +40,7 @@ proc rawImportSymbol(c: PContext, s: PSym) = for j in countup(0, sonsLen(etyp.n) - 1): var e = etyp.n.sons[j].sym if e.kind != skEnumField: - internalError(s.info, "rawImportSymbol") + internalError(c.config, s.info, "rawImportSymbol") # BUGFIX: because of aliases for enums the symbol may already # have been put into the symbol table # BUGFIX: but only iff they are the same symbols! @@ -62,14 +62,14 @@ proc rawImportSymbol(c: PContext, s: PSym) = if hasPattern(s): addPattern(c, s) proc importSymbol(c: PContext, n: PNode, fromMod: PSym) = - let ident = lookups.considerQuotedIdent(n) + let ident = lookups.considerQuotedIdent(c.config, n) let s = strTableGet(fromMod.tab, ident) if s == nil: errorUndeclaredIdentifier(c, n.info, ident.s) else: if s.kind == skStub: loadStub(s) if s.kind notin ExportableSymKinds: - internalError(n.info, "importSymbol: 2") + internalError(c.config, n.info, "importSymbol: 2") # for an enumeration we have to add all identifiers case s.kind of skProcKinds: @@ -77,7 +77,7 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) = var it: TIdentIter var e = initIdentIter(it, fromMod.tab, s.name) while e != nil: - if e.name.id != s.name.id: internalError(n.info, "importSymbol: 3") + if e.name.id != s.name.id: internalError(c.config, n.info, "importSymbol: 3") rawImportSymbol(c, e) e = nextIdentIter(it, fromMod.tab) else: rawImportSymbol(c, s) @@ -89,7 +89,7 @@ proc importAllSymbolsExcept(c: PContext, fromMod: PSym, exceptSet: IntSet) = if s.kind != skModule: if s.kind != skEnumField: if s.kind notin ExportableSymKinds: - internalError(s.info, "importAllSymbols: " & $s.kind) + internalError(c.config, s.info, "importAllSymbols: " & $s.kind) if exceptSet.isNil or s.name.id notin exceptSet: rawImportSymbol(c, s) s = nextIter(i, fromMod.tab) @@ -110,22 +110,22 @@ proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet) = elif exceptSet.isNil or s.name.id notin exceptSet: rawImportSymbol(c, s) of nkExportExceptStmt: - localError(n.info, errGenerated, "'export except' not implemented") + localError(c.config, n.info, "'export except' not implemented") else: for i in 0..safeLen(n)-1: importForwarded(c, n.sons[i], exceptSet) -proc importModuleAs(n: PNode, realModule: PSym): PSym = +proc importModuleAs(c: PContext; n: PNode, realModule: PSym): PSym = result = realModule if n.kind != nkImportAs: discard elif n.len != 2 or n.sons[1].kind != nkIdent: - localError(n.info, errGenerated, "module alias must be an identifier") + localError(c.config, n.info, "module alias must be an identifier") elif n.sons[1].ident.id != realModule.name.id: # some misguided guy will write 'import abc.foo as foo' ... result = createModuleAlias(realModule, n.sons[1].ident, realModule.info) proc myImportModule(c: PContext, n: PNode): PSym = - var f = checkModuleName(n) + var f = checkModuleName(c.config, n) if f != InvalidFileIDX: let L = c.graph.importStack.len let recursion = c.graph.importStack.find(f) @@ -138,7 +138,7 @@ proc myImportModule(c: PContext, n: PNode): PSym = err.add toFullPath(c.graph.importStack[i]) & " imports " & toFullPath(c.graph.importStack[i+1]) c.recursiveDep = err - result = importModuleAs(n, gImportModule(c.graph, c.module, f, c.cache)) + result = importModuleAs(c, n, gImportModule(c.graph, c.module, f, c.cache)) #echo "set back to ", L c.graph.importStack.setLen(L) # we cannot perform this check reliably because of @@ -146,12 +146,12 @@ proc myImportModule(c: PContext, n: PNode): PSym = when true: if result.info.fileIndex == c.module.info.fileIndex and result.info.fileIndex == n.info.fileIndex: - localError(n.info, errGenerated, "A module cannot import itself") + localError(c.config, n.info, "A module cannot import itself") if sfDeprecated in result.flags: if result.constraint != nil: - message(n.info, warnDeprecated, result.constraint.strVal & "; " & result.name.s) + message(c.config, n.info, warnDeprecated, result.constraint.strVal & "; " & result.name.s) else: - message(n.info, warnDeprecated, result.name.s) + message(c.config, n.info, warnDeprecated, result.name.s) suggestSym(n.info, result, c.graph.usageSym, false) proc impMod(c: PContext; it: PNode) = @@ -182,7 +182,7 @@ proc evalImport(c: PContext, n: PNode): PNode = proc evalFrom(c: PContext, n: PNode): PNode = result = n - checkMinSonsLen(n, 2) + checkMinSonsLen(n, 2, c.config) var m = myImportModule(c, n.sons[0]) if m != nil: n.sons[0] = newSymNode(m) @@ -193,14 +193,14 @@ proc evalFrom(c: PContext, n: PNode): PNode = proc evalImportExcept*(c: PContext, n: PNode): PNode = result = n - checkMinSonsLen(n, 2) + checkMinSonsLen(n, 2, c.config) var m = myImportModule(c, n.sons[0]) if m != nil: n.sons[0] = newSymNode(m) addDecl(c, m, n.info) # add symbol to symbol table of module var exceptSet = initIntSet() for i in countup(1, sonsLen(n) - 1): - let ident = lookups.considerQuotedIdent(n.sons[i]) + let ident = lookups.considerQuotedIdent(c.config, n.sons[i]) exceptSet.incl(ident.id) importAllSymbolsExcept(c, m, exceptSet) #importForwarded(c, m.ast, exceptSet) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 5aa903771..31d3f75a3 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -12,7 +12,7 @@ import os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer, wordrecg, ropes, options, strutils, extccomp, math, magicsys, trees, - rodread, types, lookups + rodread, types, lookups, configuration const FirstCallConv* = wNimcall @@ -84,8 +84,12 @@ proc getPragmaVal*(procAst: PNode; name: TSpecialWord): PNode = proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) # implementation -proc invalidPragma*(n: PNode) = - localError(n.info, errInvalidPragmaX, renderTree(n, {renderNoComments})) +const + errStringLiteralExpected = "string literal expected" + errIntLiteralExpected = "integer literal expected" + +proc invalidPragma*(c: PContext; n: PNode) = + localError(c.config, n.info, "invalid pragma: " % renderTree(n, {renderNoComments})) proc pragmaAsm*(c: PContext, n: PNode): char = result = '\0' @@ -96,12 +100,12 @@ proc pragmaAsm*(c: PContext, n: PNode): char = case whichKeyword(it.sons[0].ident) of wSubsChar: if it.sons[1].kind == nkCharLit: result = chr(int(it.sons[1].intVal)) - else: invalidPragma(it) - else: invalidPragma(it) + else: invalidPragma(c, it) + else: invalidPragma(c, it) else: - invalidPragma(it) + invalidPragma(c, it) -proc setExternName(s: PSym, extname: string, info: TLineInfo) = +proc setExternName(c: PContext; s: PSym, extname: string, info: TLineInfo) = # special cases to improve performance: if extname == "$1": s.loc.r = rope(s.name.s) @@ -111,28 +115,28 @@ proc setExternName(s: PSym, extname: string, info: TLineInfo) = try: s.loc.r = rope(extname % s.name.s) except ValueError: - localError(info, "invalid extern name: '" & extname & "'. (Forgot to escape '$'?)") + localError(c.config, info, "invalid extern name: '" & extname & "'. (Forgot to escape '$'?)") if gCmd == cmdPretty and '$' notin extname: # note that '{.importc.}' is transformed into '{.importc: "$1".}' s.loc.flags.incl(lfFullExternalName) -proc makeExternImport(s: PSym, extname: string, info: TLineInfo) = - setExternName(s, extname, info) +proc makeExternImport(c: PContext; s: PSym, extname: string, info: TLineInfo) = + setExternName(c, s, extname, info) incl(s.flags, sfImportc) excl(s.flags, sfForward) -proc makeExternExport(s: PSym, extname: string, info: TLineInfo) = - setExternName(s, extname, info) +proc makeExternExport(c: PContext; s: PSym, extname: string, info: TLineInfo) = + setExternName(c, s, extname, info) incl(s.flags, sfExportc) -proc processImportCompilerProc(s: PSym, extname: string, info: TLineInfo) = - setExternName(s, extname, info) +proc processImportCompilerProc(c: PContext; s: PSym, extname: string, info: TLineInfo) = + setExternName(c, s, extname, info) incl(s.flags, sfImportc) excl(s.flags, sfForward) incl(s.loc.flags, lfImportCompilerProc) -proc processImportCpp(s: PSym, extname: string, info: TLineInfo) = - setExternName(s, extname, info) +proc processImportCpp(c: PContext; s: PSym, extname: string, info: TLineInfo) = + setExternName(c, s, extname, info) incl(s.flags, sfImportc) incl(s.flags, sfInfixCall) excl(s.flags, sfForward) @@ -141,43 +145,43 @@ proc processImportCpp(s: PSym, extname: string, info: TLineInfo) = incl(m.flags, sfCompileToCpp) extccomp.gMixedMode = true -proc processImportObjC(s: PSym, extname: string, info: TLineInfo) = - setExternName(s, extname, info) +proc processImportObjC(c: PContext; s: PSym, extname: string, info: TLineInfo) = + setExternName(c, s, extname, info) incl(s.flags, sfImportc) incl(s.flags, sfNamedParamCall) excl(s.flags, sfForward) let m = s.getModule() incl(m.flags, sfCompileToObjC) -proc newEmptyStrNode(n: PNode): PNode {.noinline.} = - result = newNodeIT(nkStrLit, n.info, getSysType(tyString)) +proc newEmptyStrNode(c: PContext; n: PNode): PNode {.noinline.} = + result = newNodeIT(nkStrLit, n.info, getSysType(c.graph, n.info, tyString)) result.strVal = "" proc getStrLitNode(c: PContext, n: PNode): PNode = if n.kind notin nkPragmaCallKinds or n.len != 2: - localError(n.info, errStringLiteralExpected) + localError(c.config, n.info, errStringLiteralExpected) # error correction: - result = newEmptyStrNode(n) + result = newEmptyStrNode(c, n) else: n.sons[1] = c.semConstExpr(c, n.sons[1]) case n.sons[1].kind of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1] else: - localError(n.info, errStringLiteralExpected) + localError(c.config, n.info, errStringLiteralExpected) # error correction: - result = newEmptyStrNode(n) + result = newEmptyStrNode(c, n) proc expectStrLit(c: PContext, n: PNode): string = result = getStrLitNode(c, n).strVal proc expectIntLit(c: PContext, n: PNode): int = if n.kind notin nkPragmaCallKinds or n.len != 2: - localError(n.info, errIntLiteralExpected) + localError(c.config, n.info, errIntLiteralExpected) else: n.sons[1] = c.semConstExpr(c, n.sons[1]) case n.sons[1].kind of nkIntLit..nkInt64Lit: result = int(n.sons[1].intVal) - else: localError(n.info, errIntLiteralExpected) + else: localError(c.config, n.info, errIntLiteralExpected) proc getOptionalStr(c: PContext, n: PNode, defaultStr: string): string = if n.kind in nkPragmaCallKinds: result = expectStrLit(c, n) @@ -190,7 +194,7 @@ proc processMagic(c: PContext, n: PNode, s: PSym) = #if sfSystemModule notin c.module.flags: # liMessage(n.info, errMagicOnlyInSystem) if n.kind notin nkPragmaCallKinds or n.len != 2: - localError(n.info, errStringLiteralExpected) + localError(c.config, n.info, errStringLiteralExpected) return var v: string if n.sons[1].kind == nkIdent: v = n.sons[1].ident.s @@ -199,7 +203,7 @@ proc processMagic(c: PContext, n: PNode, s: PSym) = if substr($m, 1) == v: s.magic = m break - if s.magic == mNone: message(n.info, warnUnknownMagic, v) + if s.magic == mNone: message(c.config, n.info, warnUnknownMagic, v) proc wordToCallConv(sw: TSpecialWord): TCallingConvention = # this assumes that the order of special words and calling conventions is @@ -211,7 +215,7 @@ proc isTurnedOn(c: PContext, n: PNode): bool = let x = c.semConstBoolExpr(c, n.sons[1]) n.sons[1] = x if x.kind == nkIntLit: return x.intVal != 0 - localError(n.info, errOnOrOffExpected) + localError(c.config, n.info, "'on' or 'off' expected") proc onOff(c: PContext, n: PNode, op: TOptions) = if isTurnedOn(c, n): gOptions = gOptions + op @@ -227,9 +231,9 @@ proc processCallConv(c: PContext, n: PNode) = case sw of FirstCallConv..LastCallConv: c.optionStack[^1].defaultCC = wordToCallConv(sw) - else: localError(n.info, errCallConvExpected) + else: localError(c.config, n.info, "calling convention expected") else: - localError(n.info, errCallConvExpected) + localError(c.config, n.info, "calling convention expected") proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib = for it in c.libs: @@ -240,13 +244,13 @@ proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib = result.path = path c.libs.add result if path.kind in {nkStrLit..nkTripleStrLit}: - result.isOverriden = options.isDynlibOverride(path.strVal) + result.isOverriden = options.isDynlibOverride(c.config, path.strVal) proc expectDynlibNode(c: PContext, n: PNode): PNode = if n.kind notin nkPragmaCallKinds or n.len != 2: - localError(n.info, errStringLiteralExpected) + localError(c.config, n.info, errStringLiteralExpected) # error correction: - result = newEmptyStrNode(n) + result = newEmptyStrNode(c, n) else: # For the OpenGL wrapper we support: # {.dynlib: myGetProcAddr(...).} @@ -254,8 +258,8 @@ proc expectDynlibNode(c: PContext, n: PNode): PNode = if result.kind == nkSym and result.sym.kind == skConst: result = result.sym.ast # look it up if result.typ == nil or result.typ.kind notin {tyPointer, tyString, tyProc}: - localError(n.info, errStringLiteralExpected) - result = newEmptyStrNode(n) + localError(c.config, n.info, errStringLiteralExpected) + result = newEmptyStrNode(c, n) proc processDynLib(c: PContext, n: PNode, sym: PSym) = if (sym == nil) or (sym.kind == skModule): @@ -278,39 +282,37 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) = sym.typ.callConv = ccCDecl proc processNote(c: PContext, n: PNode) = - if (n.kind in nkPragmaCallKinds) and (sonsLen(n) == 2) and - (n.sons[0].kind == nkBracketExpr) and - (n.sons[0].sons.len == 2) and - (n.sons[0].sons[1].kind == nkIdent) and - (n.sons[0].sons[0].kind == nkIdent): - #and (n.sons[1].kind == nkIdent): + if n.kind in nkPragmaCallKinds and len(n) == 2 and + n[0].kind == nkBracketExpr and + n[0].len == 2 and + n[0][1].kind == nkIdent and n[0][0].kind == nkIdent: var nk: TNoteKind - case whichKeyword(n.sons[0].sons[0].ident) + case whichKeyword(n[0][0].ident) of wHint: - var x = findStr(msgs.HintsToStr, n.sons[0].sons[1].ident.s) + var x = findStr(HintsToStr, n[0][1].ident.s) if x >= 0: nk = TNoteKind(x + ord(hintMin)) - else: invalidPragma(n); return + else: invalidPragma(c, n); return of wWarning: - var x = findStr(msgs.WarningsToStr, n.sons[0].sons[1].ident.s) + var x = findStr(WarningsToStr, n[0][1].ident.s) if x >= 0: nk = TNoteKind(x + ord(warnMin)) - else: invalidPragma(n); return + else: invalidPragma(c, n); return else: - invalidPragma(n) + invalidPragma(c, n) return - let x = c.semConstBoolExpr(c, n.sons[1]) + let x = c.semConstBoolExpr(c, n[1]) n.sons[1] = x - if x.kind == nkIntLit and x.intVal != 0: incl(gNotes, nk) - else: excl(gNotes, nk) + if x.kind == nkIntLit and x.intVal != 0: incl(c.config.notes, nk) + else: excl(c.config.notes, nk) else: - invalidPragma(n) + invalidPragma(c, n) proc processOption(c: PContext, n: PNode): bool = if n.kind notin nkPragmaCallKinds or n.len != 2: result = true elif n.sons[0].kind == nkBracketExpr: processNote(c, n) elif n.sons[0].kind != nkIdent: result = true else: - var sw = whichKeyword(n.sons[0].ident) + let sw = whichKeyword(n.sons[0].ident) case sw of wChecks: onOff(c, n, ChecksOptions) of wObjChecks: onOff(c, n, {optObjCheck}) @@ -337,7 +339,7 @@ proc processOption(c: PContext, n: PNode): bool = of wDynlib: processDynLib(c, n, nil) of wOptimization: if n.sons[1].kind != nkIdent: - invalidPragma(n) + invalidPragma(c, n) else: case n.sons[1].ident.s.normalize of "speed": @@ -349,20 +351,20 @@ proc processOption(c: PContext, n: PNode): bool = of "none": excl(gOptions, optOptimizeSpeed) excl(gOptions, optOptimizeSize) - else: localError(n.info, errNoneSpeedOrSizeExpected) + else: localError(c.config, n.info, "'none', 'speed' or 'size' expected") of wImplicitStatic: onOff(c, n, {optImplicitStatic}) of wPatterns: onOff(c, n, {optPatterns}) else: result = true proc processPush(c: PContext, n: PNode, start: int) = if n.sons[start-1].kind in nkPragmaCallKinds: - localError(n.info, errGenerated, "'push' can't have arguments") - var x = newOptionEntry() + localError(c.config, n.info, "'push' cannot have arguments") + var x = newOptionEntry(c.config) var y = c.optionStack[^1] x.options = gOptions x.defaultCC = y.defaultCC x.dynlib = y.dynlib - x.notes = gNotes + x.notes = c.config.notes c.optionStack.add(x) for i in countup(start, sonsLen(n) - 1): if processOption(c, n.sons[i]): @@ -370,29 +372,29 @@ proc processPush(c: PContext, n: PNode, start: int) = if x.otherPragmas.isNil: x.otherPragmas = newNodeI(nkPragma, n.info) x.otherPragmas.add n.sons[i] - #localError(n.info, errOptionExpected) + #localError(c.config, n.info, errOptionExpected) proc processPop(c: PContext, n: PNode) = if c.optionStack.len <= 1: - localError(n.info, errAtPopWithoutPush) + localError(c.config, n.info, "{.pop.} without a corresponding {.push.}") else: gOptions = c.optionStack[^1].options - gNotes = c.optionStack[^1].notes + c.config.notes = c.optionStack[^1].notes c.optionStack.setLen(c.optionStack.len - 1) proc processDefine(c: PContext, n: PNode) = - if (n.kind in nkPragmaCallKinds and n.len == 2) and (n.sons[1].kind == nkIdent): - defineSymbol(n.sons[1].ident.s) - message(n.info, warnDeprecated, "define") + if (n.kind in nkPragmaCallKinds and n.len == 2) and (n[1].kind == nkIdent): + defineSymbol(c.config.symbols, n[1].ident.s) + message(c.config, n.info, warnDeprecated, "define") else: - invalidPragma(n) + invalidPragma(c, n) proc processUndef(c: PContext, n: PNode) = - if (n.kind in nkPragmaCallKinds and n.len == 2) and (n.sons[1].kind == nkIdent): - undefSymbol(n.sons[1].ident.s) - message(n.info, warnDeprecated, "undef") + if (n.kind in nkPragmaCallKinds and n.len == 2) and (n[1].kind == nkIdent): + undefSymbol(c.config.symbols, n[1].ident.s) + message(c.config, n.info, warnDeprecated, "undef") else: - invalidPragma(n) + invalidPragma(c, n) type TLinkFeature = enum @@ -406,18 +408,18 @@ proc relativeFile(c: PContext; n: PNode; ext=""): string = if not fileExists(result): if isAbsolute(s): result = s else: - result = findFile(s) + result = findFile(c.config, s) if result.len == 0: result = s proc processCompile(c: PContext, n: PNode) = proc getStrLit(c: PContext, n: PNode; i: int): string = - n.sons[i] = c.semConstExpr(c, n.sons[i]) - case n.sons[i].kind + n.sons[i] = c.semConstExpr(c, n[i]) + case n[i].kind of nkStrLit, nkRStrLit, nkTripleStrLit: - shallowCopy(result, n.sons[i].strVal) + shallowCopy(result, n[i].strVal) else: - localError(n.info, errStringLiteralExpected) + localError(c.config, n.info, errStringLiteralExpected) result = "" let it = if n.kind in nkPragmaCallKinds and n.len == 2: n.sons[1] else: n @@ -428,26 +430,27 @@ proc processCompile(c: PContext, n: PNode) = for f in os.walkFiles(found): let nameOnly = extractFilename(f) var cf = Cfile(cname: f, - obj: completeCFilePath(dest % nameOnly), + obj: completeCFilePath(c.config, dest % nameOnly), flags: {CfileFlag.External}) - extccomp.addExternalFileToCompile(cf) + extccomp.addExternalFileToCompile(c.config, cf) else: let s = expectStrLit(c, n) var found = parentDir(n.info.toFullPath) / s if not fileExists(found): if isAbsolute(s): found = s else: - found = findFile(s) + found = findFile(c.config, s) if found.len == 0: found = s - extccomp.addExternalFileToCompile(found) + extccomp.addExternalFileToCompile(c.config, found) proc processCommonLink(c: PContext, n: PNode, feature: TLinkFeature) = let found = relativeFile(c, n, CC[cCompiler].objExt) case feature - of linkNormal: extccomp.addExternalFileToLink(found) + of linkNormal: extccomp.addExternalFileToLink(c.config, found) of linkSys: - extccomp.addExternalFileToLink(libpath / completeCFilePath(found, false)) - else: internalError(n.info, "processCommonLink") + extccomp.addExternalFileToLink(c.config, + c.config.libpath / completeCFilePath(c.config, found, false)) + else: internalError(c.config, n.info, "processCommonLink") proc pragmaBreakpoint(c: PContext, n: PNode) = discard getOptionalStr(c, n, "") @@ -456,7 +459,7 @@ proc pragmaWatchpoint(c: PContext, n: PNode) = if n.kind in nkPragmaCallKinds and n.len == 2: n.sons[1] = c.semExpr(c, n.sons[1]) else: - invalidPragma(n) + invalidPragma(c, n) proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode = case n.sons[1].kind @@ -464,7 +467,7 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode = result = newNode(if n.kind == nkAsmStmt: nkAsmStmt else: nkArgList, n.info) var str = n.sons[1].strVal if str == "": - localError(n.info, errEmptyAsm) + localError(con.config, n.info, "empty 'asm' statement") return # now parse the string literal and substitute symbols: var a = 0 @@ -490,12 +493,12 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode = if c < 0: break a = c + 1 else: - illFormedAstLocal(n) + illFormedAstLocal(n, con.config) result = newNode(nkAsmStmt, n.info) proc pragmaEmit(c: PContext, n: PNode) = if n.kind notin nkPragmaCallKinds or n.len != 2: - localError(n.info, errStringLiteralExpected) + localError(c.config, n.info, errStringLiteralExpected) else: let n1 = n[1] if n1.kind == nkBracket: @@ -509,20 +512,20 @@ proc pragmaEmit(c: PContext, n: PNode) = of nkStrLit, nkRStrLit, nkTripleStrLit: n.sons[1] = semAsmOrEmit(c, n, '`') else: - localError(n.info, errStringLiteralExpected) + localError(c.config, n.info, errStringLiteralExpected) -proc noVal(n: PNode) = - if n.kind in nkPragmaCallKinds and n.len > 1: invalidPragma(n) +proc noVal(c: PContext; n: PNode) = + if n.kind in nkPragmaCallKinds and n.len > 1: invalidPragma(c, n) proc pragmaUnroll(c: PContext, n: PNode) = if c.p.nestedLoopCounter <= 0: - invalidPragma(n) + invalidPragma(c, n) elif n.kind in nkPragmaCallKinds and n.len == 2: var unrollFactor = expectIntLit(c, n) if unrollFactor <% 32: n.sons[1] = newIntNode(nkIntLit, unrollFactor) else: - invalidPragma(n) + invalidPragma(c, n) proc pragmaLine(c: PContext, n: PNode) = if n.kind in nkPragmaCallKinds and n.len == 2: @@ -535,24 +538,24 @@ proc pragmaLine(c: PContext, n: PNode) = if x.kind == nkExprColonExpr: x = x.sons[1] if y.kind == nkExprColonExpr: y = y.sons[1] if x.kind != nkStrLit: - localError(n.info, errStringLiteralExpected) + localError(c.config, n.info, errStringLiteralExpected) elif y.kind != nkIntLit: - localError(n.info, errIntLiteralExpected) + localError(c.config, n.info, errIntLiteralExpected) else: # XXX this produces weird paths which are not properly resolved: - n.info.fileIndex = msgs.fileInfoIdx(x.strVal) + n.info.fileIndex = msgs.fileInfoIdx(c.config, x.strVal) n.info.line = uint16(y.intVal) else: - localError(n.info, errXExpected, "tuple") + localError(c.config, n.info, "tuple expected") else: # sensible default: n.info = getInfoContext(-1) proc processPragma(c: PContext, n: PNode, i: int) = let it = n[i] - if it.kind notin nkPragmaCallKinds and it.len == 2: invalidPragma(n) - elif it[0].kind != nkIdent: invalidPragma(n) - elif it[1].kind != nkIdent: invalidPragma(n) + if it.kind notin nkPragmaCallKinds and it.len == 2: invalidPragma(c, n) + elif it[0].kind != nkIdent: invalidPragma(c, n) + elif it[1].kind != nkIdent: invalidPragma(c, n) var userPragma = newSym(skTemplate, it[1].ident, nil, it.info) userPragma.ast = newNode(nkPragma, n.info, n.sons[i+1..^1]) @@ -562,7 +565,7 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) = proc processExc(c: PContext, x: PNode) = var t = skipTypes(c.semTypeNode(c, x, nil), skipPtrs) if t.kind != tyObject: - localError(x.info, errGenerated, "invalid type for raises/tags list") + localError(c.config, x.info, errGenerated, "invalid type for raises/tags list") x.typ = t if n.kind in nkPragmaCallKinds and n.len == 2: @@ -572,51 +575,51 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) = else: for e in items(it): processExc(c, e) else: - invalidPragma(n) + invalidPragma(c, n) proc pragmaLockStmt(c: PContext; it: PNode) = if it.kind notin nkPragmaCallKinds or it.len != 2: - invalidPragma(it) + invalidPragma(c, it) else: let n = it[1] if n.kind != nkBracket: - localError(n.info, errGenerated, "locks pragma takes a list of expressions") + localError(c.config, n.info, errGenerated, "locks pragma takes a list of expressions") else: for i in 0 ..< n.len: n.sons[i] = c.semExpr(c, n.sons[i]) proc pragmaLocks(c: PContext, it: PNode): TLockLevel = if it.kind notin nkPragmaCallKinds or it.len != 2: - invalidPragma(it) + invalidPragma(c, it) else: case it[1].kind of nkStrLit, nkRStrLit, nkTripleStrLit: if it[1].strVal == "unknown": result = UnknownLockLevel else: - localError(it[1].info, "invalid string literal for locks pragma (only allowed string is \"unknown\")") + localError(c.config, it[1].info, "invalid string literal for locks pragma (only allowed string is \"unknown\")") else: let x = expectIntLit(c, it) if x < 0 or x > MaxLockLevel: - localError(it[1].info, "integer must be within 0.." & $MaxLockLevel) + localError(c.config, it[1].info, "integer must be within 0.." & $MaxLockLevel) else: result = TLockLevel(x) -proc typeBorrow(sym: PSym, n: PNode) = +proc typeBorrow(c: PContext; sym: PSym, n: PNode) = if n.kind in nkPragmaCallKinds and n.len == 2: let it = n.sons[1] if it.kind != nkAccQuoted: - localError(n.info, "a type can only borrow `.` for now") + localError(c.config, n.info, "a type can only borrow `.` for now") incl(sym.typ.flags, tfBorrowDot) -proc markCompilerProc(s: PSym) = +proc markCompilerProc(c: PContext; s: PSym) = # minor hack ahead: FlowVar is the only generic .compilerProc type which # should not have an external name set: if s.kind != skType or s.name.s != "FlowVar": - makeExternExport(s, "$1", s.info) + makeExternExport(c, s, "$1", s.info) incl(s.flags, sfCompilerProc) incl(s.flags, sfUsed) - registerCompilerProc(s) + registerCompilerProc(c.graph, s) proc deprecatedStmt(c: PContext; outerPragma: PNode) = let pragma = outerPragma[1] @@ -625,24 +628,24 @@ proc deprecatedStmt(c: PContext; outerPragma: PNode) = c.module.constraint = getStrLitNode(c, outerPragma) return if pragma.kind != nkBracket: - localError(pragma.info, "list of key:value pairs expected"); return + localError(c.config, pragma.info, "list of key:value pairs expected"); return for n in pragma: if n.kind in nkPragmaCallKinds and n.len == 2: let dest = qualifiedLookUp(c, n[1], {checkUndeclared}) if dest == nil or dest.kind in routineKinds: - localError(n.info, warnUser, "the .deprecated pragma is unreliable for routines") - let src = considerQuotedIdent(n[0]) + localError(c.config, n.info, warnUser, "the .deprecated pragma is unreliable for routines") + let src = considerQuotedIdent(c.config, n[0]) let alias = newSym(skAlias, src, dest, n[0].info) incl(alias.flags, sfExported) - if sfCompilerProc in dest.flags: markCompilerProc(alias) + if sfCompilerProc in dest.flags: markCompilerProc(c, alias) addInterfaceDecl(c, alias) n.sons[1] = newSymNode(dest) else: - localError(n.info, "key:value pair expected") + localError(c.config, n.info, "key:value pair expected") proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym = if it.kind notin nkPragmaCallKinds or it.len != 2: - invalidPragma(it); return + invalidPragma(c, it); return let n = it[1] if n.kind == nkSym: result = n.sym @@ -654,7 +657,7 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym = # We return a dummy symbol; later passes over the type will repair it. # Generic instantiation needs to know about this too. But we're lazy # and perform the lookup on demand instead. - result = newSym(skUnknown, considerQuotedIdent(n), nil, n.info) + result = newSym(skUnknown, considerQuotedIdent(c.config, n), nil, n.info) else: result = qualifiedLookUp(c, n, {checkUndeclared}) @@ -667,12 +670,12 @@ proc semCustomPragma(c: PContext, n: PNode): PNode = elif n.kind in nkPragmaCallKinds + {nkIdent}: result = n else: - invalidPragma(n) + invalidPragma(c, n) return n let r = c.semOverloadedCall(c, result, n, {skTemplate}, {}) if r.isNil or sfCustomPragma notin r[0].sym.flags: - invalidPragma(n) + invalidPragma(c, n) else: result = r if n.kind == nkIdent: @@ -682,7 +685,7 @@ proc semCustomPragma(c: PContext, n: PNode): PNode = proc processExperimental(c: PContext; n: PNode; s: PSym) = if not isTopLevel(c): - localError(n.info, "'experimental' pragma only valid as toplevel statement") + localError(c.config, n.info, "'experimental' pragma only valid as toplevel statement") if n.kind notin nkPragmaCallKinds or n.len != 2: c.features.incl oldExperimentalFeatures else: @@ -692,9 +695,9 @@ proc processExperimental(c: PContext; n: PNode; s: PSym) = try: c.features.incl parseEnum[Feature](n[1].strVal) except ValueError: - localError(n[1].info, "unknown experimental feature") + localError(c.config, n[1].info, "unknown experimental feature") else: - localError(n.info, errStringLiteralExpected) + localError(c.config, n.info, errStringLiteralExpected) proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, validPragmas: TSpecialWords): bool = @@ -706,13 +709,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, elif key.kind notin nkIdentKinds: n.sons[i] = semCustomPragma(c, it) return - let ident = considerQuotedIdent(key) + let ident = considerQuotedIdent(c.config, key) var userPragma = strTableGet(c.userPragmas, ident) if userPragma != nil: # number of pragmas increase/decrease with user pragma expansion inc c.instCounter if c.instCounter > 100: - globalError(it.info, errRecursiveDependencyX, userPragma.name.s) + globalError(c.config, it.info, "recursive dependency: " & userPragma.name.s) pragma(c, sym, userPragma.ast, validPragmas) n.sons[i..i] = userPragma.ast.sons # expand user pragma with its content @@ -723,78 +726,78 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, if k in validPragmas: case k of wExportc: - makeExternExport(sym, getOptionalStr(c, it, "$1"), it.info) + makeExternExport(c, sym, getOptionalStr(c, it, "$1"), it.info) incl(sym.flags, sfUsed) # avoid wrong hints of wImportc: let name = getOptionalStr(c, it, "$1") - cppDefine(c.graph.config, name) - makeExternImport(sym, name, it.info) + cppDefine(c.config, name) + makeExternImport(c, sym, name, it.info) of wImportCompilerProc: let name = getOptionalStr(c, it, "$1") - cppDefine(c.graph.config, name) - processImportCompilerProc(sym, name, it.info) - of wExtern: setExternName(sym, expectStrLit(c, it), it.info) + cppDefine(c.config, name) + processImportCompilerProc(c, sym, name, it.info) + of wExtern: setExternName(c, sym, expectStrLit(c, it), it.info) of wImmediate: if sym.kind in {skTemplate, skMacro}: incl(sym.flags, sfImmediate) incl(sym.flags, sfAllUntyped) - message(n.info, warnDeprecated, "use 'untyped' parameters instead; immediate") - else: invalidPragma(it) + message(c.config, n.info, warnDeprecated, "use 'untyped' parameters instead; immediate") + else: invalidPragma(c, it) of wDirty: if sym.kind == skTemplate: incl(sym.flags, sfDirty) - else: invalidPragma(it) + else: invalidPragma(c, it) of wImportCpp: - processImportCpp(sym, getOptionalStr(c, it, "$1"), it.info) + processImportCpp(c, sym, getOptionalStr(c, it, "$1"), it.info) of wImportObjC: - processImportObjC(sym, getOptionalStr(c, it, "$1"), it.info) + processImportObjC(c, sym, getOptionalStr(c, it, "$1"), it.info) of wAlign: - if sym.typ == nil: invalidPragma(it) + if sym.typ == nil: invalidPragma(c, it) var align = expectIntLit(c, it) if (not isPowerOfTwo(align) and align != 0) or align >% high(int16): - localError(it.info, errPowerOfTwoExpected) + localError(c.config, it.info, "power of two expected") else: sym.typ.align = align.int16 of wSize: - if sym.typ == nil: invalidPragma(it) + if sym.typ == nil: invalidPragma(c, it) var size = expectIntLit(c, it) if not isPowerOfTwo(size) or size <= 0 or size > 8: - localError(it.info, errPowerOfTwoExpected) + localError(c.config, it.info, "power of two expected") else: sym.typ.size = size of wNodecl: - noVal(it) + noVal(c, it) incl(sym.loc.flags, lfNoDecl) of wPure, wAsmNoStackFrame: - noVal(it) + noVal(c, it) if sym != nil: - if k == wPure and sym.kind in routineKinds: invalidPragma(it) + if k == wPure and sym.kind in routineKinds: invalidPragma(c, it) else: incl(sym.flags, sfPure) of wVolatile: - noVal(it) + noVal(c, it) incl(sym.flags, sfVolatile) of wRegister: - noVal(it) + noVal(c, it) incl(sym.flags, sfRegister) of wThreadVar: - noVal(it) + noVal(c, it) incl(sym.flags, sfThread) of wDeadCodeElimUnused: discard # deprecated, dead code elim always on of wNoForward: pragmaNoForward(c, it) of wReorder: pragmaNoForward(c, it, sfReorder) of wMagic: processMagic(c, it, sym) of wCompileTime: - noVal(it) + noVal(c, it) incl(sym.flags, sfCompileTime) incl(sym.loc.flags, lfNoDecl) of wGlobal: - noVal(it) + noVal(c, it) incl(sym.flags, sfGlobal) incl(sym.flags, sfPure) of wMerge: # only supported for backwards compat, doesn't do anything anymore - noVal(it) + noVal(c, it) of wConstructor: - noVal(it) + noVal(c, it) incl(sym.flags, sfConstructor) of wHeader: var lib = getLib(c, libHeader, getStrLitNode(c, it)) @@ -807,25 +810,26 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, of wOverride: sym.flags.incl sfOverriden of wNosideeffect: - noVal(it) + noVal(c, it) incl(sym.flags, sfNoSideEffect) if sym.typ != nil: incl(sym.typ.flags, tfNoSideEffect) of wSideeffect: - noVal(it) + noVal(c, it) incl(sym.flags, sfSideEffect) of wNoreturn: - noVal(it) + noVal(c, it) incl(sym.flags, sfNoReturn) if sym.typ[0] != nil: - localError(sym.ast[paramsPos][0].info, errNoReturnWithReturnTypeNotAllowed) + localError(c.config, sym.ast[paramsPos][0].info, + ".noreturn with return type not allowed") of wDynlib: processDynLib(c, it, sym) of wCompilerProc, wCore: - noVal(it) # compilerproc may not get a string! + noVal(c, it) # compilerproc may not get a string! cppDefine(c.graph.config, sym.name.s) - if sfFromGeneric notin sym.flags: markCompilerProc(sym) + if sfFromGeneric notin sym.flags: markCompilerProc(c, sym) of wProcVar: - noVal(it) + noVal(c, it) incl(sym.flags, sfProcvar) of wExplain: sym.flags.incl sfExplain @@ -837,74 +841,74 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, elif sym != nil: incl(sym.flags, sfDeprecated) else: incl(c.module.flags, sfDeprecated) of wVarargs: - noVal(it) - if sym.typ == nil: invalidPragma(it) + noVal(c, it) + if sym.typ == nil: invalidPragma(c, it) else: incl(sym.typ.flags, tfVarargs) of wBorrow: if sym.kind == skType: - typeBorrow(sym, it) + typeBorrow(c, sym, it) else: - noVal(it) + noVal(c, it) incl(sym.flags, sfBorrow) of wFinal: - noVal(it) - if sym.typ == nil: invalidPragma(it) + noVal(c, it) + if sym.typ == nil: invalidPragma(c, it) else: incl(sym.typ.flags, tfFinal) of wInheritable: - noVal(it) - if sym.typ == nil or tfFinal in sym.typ.flags: invalidPragma(it) + noVal(c, it) + if sym.typ == nil or tfFinal in sym.typ.flags: invalidPragma(c, it) else: incl(sym.typ.flags, tfInheritable) of wPackage: - noVal(it) - if sym.typ == nil: invalidPragma(it) + noVal(c, it) + if sym.typ == nil: invalidPragma(c, it) else: incl(sym.flags, sfForward) of wAcyclic: - noVal(it) - if sym.typ == nil: invalidPragma(it) + noVal(c, it) + if sym.typ == nil: invalidPragma(c, it) else: incl(sym.typ.flags, tfAcyclic) of wShallow: - noVal(it) - if sym.typ == nil: invalidPragma(it) + noVal(c, it) + if sym.typ == nil: invalidPragma(c, it) else: incl(sym.typ.flags, tfShallow) of wThread: - noVal(it) + noVal(c, it) incl(sym.flags, sfThread) incl(sym.flags, sfProcvar) if sym.typ != nil: incl(sym.typ.flags, tfThread) if sym.typ.callConv == ccClosure: sym.typ.callConv = ccDefault of wGcSafe: - noVal(it) + noVal(c, it) if sym != nil: if sym.kind != skType: incl(sym.flags, sfThread) if sym.typ != nil: incl(sym.typ.flags, tfGcSafe) - else: invalidPragma(it) + else: invalidPragma(c, it) else: discard "no checking if used as a code block" of wPacked: - noVal(it) - if sym.typ == nil: invalidPragma(it) + noVal(c, it) + if sym.typ == nil: invalidPragma(c, it) else: incl(sym.typ.flags, tfPacked) - of wHint: message(it.info, hintUser, expectStrLit(c, it)) - of wWarning: message(it.info, warnUser, expectStrLit(c, it)) + of wHint: message(c.config, it.info, hintUser, expectStrLit(c, it)) + of wWarning: message(c.config, 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) + noVal(c, it) incl(sym.flags, sfError) else: - localError(it.info, errUser, expectStrLit(c, it)) - of wFatal: fatal(it.info, errUser, expectStrLit(c, it)) + localError(c.config, it.info, errUser, expectStrLit(c, it)) + of wFatal: fatal(c.config, 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 wPassl: extccomp.addLinkOption(c.config, expectStrLit(c, it)) + of wPassc: extccomp.addCompileOption(c.config, expectStrLit(c, it)) of wBreakpoint: pragmaBreakpoint(c, it) of wWatchPoint: pragmaWatchpoint(c, it) of wPush: @@ -918,10 +922,10 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, processPragma(c, n, i) result = true of wDiscardable: - noVal(it) + noVal(c, it) if sym != nil: incl(sym.flags, sfDiscardable) of wNoInit: - noVal(it) + noVal(c, it) if sym != nil: incl(sym.flags, sfNoInit) of wCodegenDecl: processCodegenDecl(c, it, sym) of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks, @@ -932,106 +936,106 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int, wPatterns: if processOption(c, it): # calling conventions (boring...): - localError(it.info, errOptionExpected) + localError(c.config, it.info, "option expected") of FirstCallConv..LastCallConv: assert(sym != nil) - if sym.typ == nil: invalidPragma(it) + if sym.typ == nil: invalidPragma(c, it) else: sym.typ.callConv = wordToCallConv(k) of wEmit: pragmaEmit(c, it) of wUnroll: pragmaUnroll(c, it) - of wLinearScanEnd, wComputedGoto: noVal(it) + of wLinearScanEnd, wComputedGoto: noVal(c, it) of wEffects: # is later processed in effect analysis: - noVal(it) + noVal(c, it) of wIncompleteStruct: - noVal(it) - if sym.typ == nil: invalidPragma(it) + noVal(c, it) + if sym.typ == nil: invalidPragma(c, it) else: incl(sym.typ.flags, tfIncompleteStruct) of wUnchecked: - noVal(it) - if sym.typ == nil: invalidPragma(it) + noVal(c, it) + if sym.typ == nil: invalidPragma(c, it) else: incl(sym.typ.flags, tfUncheckedArray) of wUnion: - noVal(it) - if sym.typ == nil: invalidPragma(it) + noVal(c, it) + if sym.typ == nil: invalidPragma(c, it) else: incl(sym.typ.flags, tfUnion) of wRequiresInit: - noVal(it) - if sym.typ == nil: invalidPragma(it) + noVal(c, it) + if sym.typ == nil: invalidPragma(c, it) else: incl(sym.typ.flags, tfNeedsInit) of wByRef: - noVal(it) + noVal(c, it) if sym == nil or sym.typ == nil: - if processOption(c, it): localError(it.info, errOptionExpected) + if processOption(c, it): localError(c.config, it.info, "option expected") else: incl(sym.typ.flags, tfByRef) of wByCopy: - noVal(it) - if sym.kind != skType or sym.typ == nil: invalidPragma(it) + noVal(c, it) + if sym.kind != skType or sym.typ == nil: invalidPragma(c, it) else: incl(sym.typ.flags, tfByCopy) of wPartial: - noVal(it) - if sym.kind != skType or sym.typ == nil: invalidPragma(it) + noVal(c, it) + if sym.kind != skType or sym.typ == nil: invalidPragma(c, it) else: incl(sym.typ.flags, tfPartial) 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) + noVal(c, it) + if sym == nil: invalidPragma(c, it) of wLine: pragmaLine(c, it) of wRaises, wTags: pragmaRaisesOrTags(c, it) of wLocks: if sym == nil: pragmaLockStmt(c, it) - elif sym.typ == nil: invalidPragma(it) + elif sym.typ == nil: invalidPragma(c, it) else: sym.typ.lockLevel = pragmaLocks(c, it) of wBitsize: if sym == nil or sym.kind != skField: - invalidPragma(it) + invalidPragma(c, it) else: sym.bitsize = expectIntLit(c, it) of wGuard: if sym == nil or sym.kind notin {skVar, skLet, skField}: - invalidPragma(it) + invalidPragma(c, it) else: sym.guard = pragmaGuard(c, it, sym.kind) of wGoto: if sym == nil or sym.kind notin {skVar, skLet}: - invalidPragma(it) + invalidPragma(c, it) else: sym.flags.incl sfGoto of wExportNims: - if sym == nil: invalidPragma(it) - else: magicsys.registerNimScriptSymbol(sym) + if sym == nil: invalidPragma(c, it) + else: magicsys.registerNimScriptSymbol(c.graph, sym) of wInjectStmt: if it.kind notin nkPragmaCallKinds or it.len != 2: - localError(it.info, errExprExpected) + localError(c.config, it.info, "expression expected") else: it.sons[1] = c.semExpr(c, it.sons[1]) of wExperimental: processExperimental(c, it, sym) of wThis: if it.kind in nkPragmaCallKinds and it.len == 2: - c.selfName = considerQuotedIdent(it[1]) + c.selfName = considerQuotedIdent(c.config, it[1]) elif it.kind == nkIdent or it.len == 1: c.selfName = getIdent("self") else: - localError(it.info, "'this' pragma is allowed to have zero or one arguments") + localError(c.config, it.info, "'this' pragma is allowed to have zero or one arguments") of wNoRewrite: - noVal(it) + noVal(c, it) of wBase: - noVal(it) + noVal(c, it) sym.flags.incl sfBase of wIntDefine: sym.magic = mIntDefine of wStrDefine: sym.magic = mStrDefine of wUsed: - noVal(it) - if sym == nil: invalidPragma(it) + noVal(c, it) + if sym == nil: invalidPragma(c, it) else: sym.flags.incl sfUsed of wLiftLocals: discard - else: invalidPragma(it) + else: invalidPragma(c, it) else: n.sons[i] = semCustomPragma(c, it) @@ -1046,12 +1050,12 @@ proc implicitPragmas*(c: PContext, sym: PSym, n: PNode, var i = 0 while i < o.len(): if singlePragma(c, sym, o, i, validPragmas): - internalError(n.info, "implicitPragmas") + internalError(c.config, n.info, "implicitPragmas") inc i popInfoContext() if lfExportLib in sym.loc.flags and sfExportc notin sym.flags: - localError(n.info, errDynlibRequiresExportc) + localError(c.config, n.info, ".dynlib requires .exportc") var lib = c.optionStack[^1].dynlib if {lfDynamicLib, lfHeader} * sym.loc.flags == {} and sfImportc in sym.flags and lib != nil: @@ -1063,7 +1067,7 @@ proc hasPragma*(n: PNode, pragma: TSpecialWord): bool = if n == nil or n.sons == nil: return false - for p in n.sons: + for p in n: var key = if p.kind in nkPragmaCallKinds and p.len > 1: p[0] else: p if key.kind == nkIdent and whichKeyword(key.ident) == pragma: return true diff --git a/compiler/procfind.nim b/compiler/procfind.nim index f7d86aaef..042947e72 100644 --- a/compiler/procfind.nim +++ b/compiler/procfind.nim @@ -14,14 +14,12 @@ import ast, astalgo, msgs, semdata, types, trees, strutils proc equalGenericParams(procA, procB: PNode): bool = - if sonsLen(procA) != sonsLen(procB): return + if sonsLen(procA) != sonsLen(procB): return false for i in countup(0, sonsLen(procA) - 1): if procA.sons[i].kind != nkSym: - internalError(procA.info, "equalGenericParams") - return + return false if procB.sons[i].kind != nkSym: - internalError(procB.info, "equalGenericParams") - return + return false let a = procA.sons[i].sym let b = procB.sons[i].sym if a.name.id != b.name.id or @@ -57,7 +55,7 @@ proc searchForProcOld*(c: PContext, scope: PScope, fn: PSym): PSym = of paramsEqual: return of paramsIncompatible: - localError(fn.info, errNotOverloadable, fn.name.s) + localError(c.config, fn.info, "overloaded '$1' leads to ambiguous calls" % fn.name.s) return of paramsNotEqual: discard @@ -76,10 +74,10 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym = let message = ("public implementation '$1' has non-public " & "forward declaration in $2") % [getProcHeader(result), $result.info] - localError(fn.info, errGenerated, message) + localError(c.config, fn.info, message) return of paramsIncompatible: - localError(fn.info, errNotOverloadable, fn.name.s) + localError(c.config, fn.info, "overloaded '$1' leads to ambiguous calls" % fn.name.s) return of paramsNotEqual: discard -- cgit 1.4.1-2-gfad0 From 328e7a100560e5bd179512ba142ef944bf0a0698 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 13 May 2018 17:52:21 +0200 Subject: options.nim: no global variables anymore --- compiler/ast.nim | 19 ++-- compiler/ccgexprs.nim | 56 +++++----- compiler/ccgstmts.nim | 14 +-- compiler/ccgthreadvars.nim | 6 +- compiler/ccgtrav.nim | 6 +- compiler/ccgtypes.nim | 4 +- compiler/cgen.nim | 102 ++++++++--------- compiler/cgendata.nim | 2 +- compiler/commands.nim | 270 ++++++++++++++++++++++----------------------- compiler/docgen.nim | 50 ++++----- compiler/docgen2.nim | 4 +- compiler/extccomp.nim | 58 +++++----- compiler/hlo.nim | 8 +- compiler/importer.nim | 3 +- compiler/jsgen.nim | 6 +- compiler/lambdalifting.nim | 23 ++-- compiler/lexer.nim | 6 +- compiler/lookups.nim | 8 +- compiler/lowerings.nim | 44 ++++---- compiler/magicsys.nim | 4 +- compiler/main.nim | 74 ++++++------- compiler/modulegraphs.nim | 2 +- compiler/modules.nim | 2 +- compiler/msgs.nim | 2 +- compiler/nim.nim | 10 +- compiler/nimconf.nim | 36 +++--- compiler/nimfix/nimfix.nim | 2 +- compiler/options.nim | 2 +- compiler/passaux.nim | 2 +- compiler/pragmas.nim | 31 +++--- compiler/renderer.nim | 4 +- compiler/rodread.nim | 15 ++- compiler/rodwrite.nim | 6 +- compiler/sem.nim | 10 +- compiler/semdata.nim | 5 +- compiler/semexprs.nim | 12 +- compiler/semfold.nim | 8 +- compiler/semgnrc.nim | 2 +- compiler/sempass2.nim | 10 +- compiler/semstmts.nim | 18 +-- compiler/semtypes.nim | 8 +- compiler/service.nim | 2 +- compiler/sigmatch.nim | 4 +- compiler/suggest.nim | 48 ++++---- compiler/syntaxes.nim | 2 +- compiler/transf.nim | 6 +- 46 files changed, 509 insertions(+), 507 deletions(-) (limited to 'compiler/pragmas.nim') diff --git a/compiler/ast.nim b/compiler/ast.nim index 6785702f1..5e65fbff9 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -734,7 +734,7 @@ type locOther # location is something other TLocFlag* = enum lfIndirect, # backend introduced a pointer - lfFullExternalName, # only used when 'gCmd == cmdPretty': Indicates + lfFullExternalName, # only used when 'conf.cmd == cmdPretty': Indicates # that the symbol has been imported via 'importc: "fullname"' and # no format string. lfNoDeepCopy, # no need for a deep copy @@ -1078,14 +1078,14 @@ template previouslyInferred*(t: PType): PType = if t.sons.len > 1: t.lastSon else: nil proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym, - info: TLineInfo): PSym = + info: TLineInfo; options: TOptions = {}): PSym = # generates a symbol and initializes the hash field too new(result) result.name = name result.kind = symKind result.flags = {} result.info = info - result.options = gOptions + result.options = options result.owner = owner result.offset = -1 result.id = getID() @@ -1095,7 +1095,7 @@ proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym, # writeStacktrace() # MessageOut(name.s & " has id: " & toString(result.id)) -var emptyNode* = newNode(nkEmpty) +var emptyNode* = newNode(nkEmpty) # XXX global variable here! # There is a single empty node that is shared! Do not overwrite it! proc isMetaType*(t: PType): bool = @@ -1325,7 +1325,7 @@ proc copyType*(t: PType, owner: PSym, keepId: bool): PType = proc exactReplica*(t: PType): PType = copyType(t, t.owner, true) proc copySym*(s: PSym, keepId: bool = false): PSym = - result = newSym(s.kind, s.name, s.owner, s.info) + result = newSym(s.kind, s.name, s.owner, s.info, s.options) #result.ast = nil # BUGFIX; was: s.ast which made problems result.typ = s.typ if keepId: @@ -1344,8 +1344,9 @@ proc copySym*(s: PSym, keepId: bool = false): PSym = if result.kind in {skVar, skLet, skField}: result.guard = s.guard -proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym = - result = newSym(s.kind, newIdent, s.owner, info) +proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo; + options: TOptions): PSym = + result = newSym(s.kind, newIdent, s.owner, info, options) # keep ID! result.ast = s.ast result.id = s.id @@ -1680,9 +1681,9 @@ proc isException*(t: PType): bool = base = base.lastSon return false -proc isImportedException*(t: PType): bool = +proc isImportedException*(t: PType; conf: ConfigRef): bool = assert(t != nil) - if optNoCppExceptions in gGlobalOptions: + if optNoCppExceptions in conf.globalOptions: return false let base = t.skipTypes({tyAlias, tyPtr, tyDistinct, tyGenericInst}) diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index dff974ddb..335aa2f84 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -13,7 +13,7 @@ proc int64Literal(i: BiggestInt): Rope = if i > low(int64): - result = rfmt(nil, "IL64($1)", rope(i)) + result = "IL64($1)" % [rope(i)] else: result = ~"(IL64(-9223372036854775807) - IL64(1))" @@ -26,7 +26,7 @@ proc intLiteral(i: BiggestInt): Rope = # Nim has the same bug for the same reasons :-) result = ~"(-2147483647 -1)" elif i > low(int64): - result = rfmt(nil, "IL64($1)", rope(i)) + result = "IL64($1)" % [rope(i)] else: result = ~"(IL64(-9223372036854775807) - IL64(1))" @@ -834,7 +834,7 @@ proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) = if field.loc.r == nil: internalError(p.config, e.info, "genCheckedRecordField") # generate the checks: genFieldCheck(p, e, r, field) - add(r, rfmt(nil, ".$1", field.loc.r)) + add(r, ropecg(p.module, ".$1", field.loc.r)) putIntoDest(p, d, e.sons[0], r, a.storage) else: genRecordField(p, e.sons[0], d) @@ -862,7 +862,7 @@ proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = localError(p.config, x.info, "index out of bounds") d.inheritLocation(a) putIntoDest(p, d, n, - rfmt(nil, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.storage) + ropecg(p.module, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.storage) proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) = var a, b: TLoc @@ -871,7 +871,7 @@ proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) = var ty = skipTypes(a.t, abstractVarRange) inheritLocation(d, a) putIntoDest(p, d, n, - rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage) + ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage) proc genIndexCheck(p: BProc; arr, idx: TLoc) = let ty = skipTypes(arr.t, abstractVarRange) @@ -899,7 +899,7 @@ proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) = rdLoc(b), rdLoc(a)) # BUGFIX: ``>=`` and not ``>``! inheritLocation(d, a) putIntoDest(p, d, n, - rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage) + ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage) proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) = var a, b: TLoc @@ -919,9 +919,9 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) = rdLoc(b), rdLoc(a), lenField(p)) if d.k == locNone: d.storage = OnHeap if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}: - a.r = rfmt(nil, "(*$1)", a.r) + a.r = ropecg(p.module, "(*$1)", a.r) putIntoDest(p, d, n, - rfmt(nil, "$1->data[$2]", rdLoc(a), rdCharLoc(b)), a.storage) + ropecg(p.module, "$1->data[$2]", rdLoc(a), rdCharLoc(b)), a.storage) proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) = var ty = skipTypes(n.sons[0].typ, abstractVarRange + tyUserTypeClasses) @@ -1004,7 +1004,7 @@ proc genEcho(p: BProc, n: PNode) = linefmt(p, cpsStmts, "fflush(stdout);$n") proc gcUsage(conf: ConfigRef; n: PNode) = - if gSelectedGC == gcNone: message(conf, n.info, warnGcMem, n.renderTree) + if conf.selectedGC == gcNone: message(conf, n.info, warnGcMem, n.renderTree) proc genStrConcat(p: BProc, e: PNode, d: var TLoc) = # @@ -1033,13 +1033,13 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, e.sons[i + 1], a) if skipTypes(e.sons[i + 1].typ, abstractVarRange).kind == tyChar: inc(L) - add(appends, rfmt(p.module, "#appendChar($1, $2);$n", tmp.r, rdLoc(a))) + add(appends, ropecg(p.module, "#appendChar($1, $2);$n", tmp.r, rdLoc(a))) else: if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}: inc(L, len(e.sons[i + 1].strVal)) else: addf(lens, "($1 ? $1->$2 : 0) + ", [rdLoc(a), lenField(p)]) - add(appends, rfmt(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a))) + add(appends, ropecg(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a))) linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, rope(L)) add(p.s(cpsStmts), appends) if d.k == locNone: @@ -1071,14 +1071,14 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, e.sons[i + 2], a) if skipTypes(e.sons[i + 2].typ, abstractVarRange).kind == tyChar: inc(L) - add(appends, rfmt(p.module, "#appendChar($1, $2);$n", + add(appends, ropecg(p.module, "#appendChar($1, $2);$n", rdLoc(dest), rdLoc(a))) else: if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}: inc(L, len(e.sons[i + 2].strVal)) else: addf(lens, "($1 ? $1->$2 : 0) + ", [rdLoc(a), lenField(p)]) - add(appends, rfmt(p.module, "#appendString($1, $2);$n", + add(appends, ropecg(p.module, "#appendString($1, $2);$n", rdLoc(dest), rdLoc(a))) linefmt(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n", rdLoc(dest), lens, rope(L)) @@ -1106,7 +1106,7 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) = initLoc(dest, locExpr, e.sons[2], OnHeap) getIntTemp(p, tmpL) lineCg(p, cpsStmts, "$1 = $2->$3++;$n", tmpL.r, rdLoc(a), lenField(p)) - dest.r = rfmt(nil, "$1->data[$2]", rdLoc(a), tmpL.r) + dest.r = ropecg(p.module, "$1->data[$2]", rdLoc(a), tmpL.r) genAssignment(p, dest, b, {needToCopy, afDestIsNil}) gcUsage(p.config, e) @@ -1280,7 +1280,7 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) = genNewSeqAux(p, dest[], intLiteral(sonsLen(n))) for i in countup(0, sonsLen(n) - 1): initLoc(arr, locExpr, n[i], OnHeap) - arr.r = rfmt(nil, "$1->data[$2]", rdLoc(dest[]), intLiteral(i)) + arr.r = ropecg(p.module, "$1->data[$2]", rdLoc(dest[]), intLiteral(i)) arr.storage = OnHeap # we know that sequences are on the heap expr(p, n[i], arr) gcUsage(p.config, n) @@ -1306,10 +1306,10 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) = if L < 10: for i in countup(0, L - 1): initLoc(elem, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap) - elem.r = rfmt(nil, "$1->data[$2]", rdLoc(d), intLiteral(i)) + elem.r = ropecg(p.module, "$1->data[$2]", rdLoc(d), intLiteral(i)) elem.storage = OnHeap # we know that sequences are on the heap initLoc(arr, locExpr, lodeTyp elemType(skipTypes(n.sons[1].typ, abstractInst)), a.storage) - arr.r = rfmt(nil, "$1[$2]", rdLoc(a), intLiteral(i)) + arr.r = ropecg(p.module, "$1[$2]", rdLoc(a), intLiteral(i)) genAssignment(p, elem, arr, {afDestIsNil, needToCopy}) else: var i: TLoc @@ -1317,10 +1317,10 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) = let oldCode = p.s(cpsStmts) linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n", i.r, L.rope) initLoc(elem, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap) - elem.r = rfmt(nil, "$1->data[$2]", rdLoc(d), rdLoc(i)) + elem.r = ropecg(p.module, "$1->data[$2]", rdLoc(d), rdLoc(i)) elem.storage = OnHeap # we know that sequences are on the heap initLoc(arr, locExpr, lodeTyp elemType(skipTypes(n.sons[1].typ, abstractInst)), a.storage) - arr.r = rfmt(nil, "$1[$2]", rdLoc(a), rdLoc(i)) + arr.r = ropecg(p.module, "$1[$2]", rdLoc(a), rdLoc(i)) genAssignment(p, elem, arr, {afDestIsNil, needToCopy}) lineF(p, cpsStmts, "}$n", []) @@ -1356,10 +1356,10 @@ proc genOfHelper(p: BProc; dest: PType; a: Rope; info: TLineInfo): Rope = inc p.module.labels let cache = "Nim_OfCheck_CACHE" & p.module.labels.rope addf(p.module.s[cfsVars], "static TNimType* $#[2];$n", [cache]) - result = rfmt(p.module, "#isObjWithCache($#.m_type, $#, $#)", a, ti, cache) + result = ropecg(p.module, "#isObjWithCache($#.m_type, $#, $#)", a, ti, cache) when false: # former version: - result = rfmt(p.module, "#isObj($1.m_type, $2)", + result = ropecg(p.module, "#isObj($1.m_type, $2)", a, genTypeInfo(p.module, dest, info)) proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) = @@ -1372,7 +1372,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) = while t.kind in {tyVar, tyLent, tyPtr, tyRef}: if t.kind notin {tyVar, tyLent}: nilCheck = r if t.kind notin {tyVar, tyLent} or not p.module.compileToCpp: - r = rfmt(nil, "(*$1)", r) + r = ropecg(p.module, "(*$1)", r) t = skipTypes(t.lastSon, typedescInst) discard getTypeDesc(p.module, t) if not p.module.compileToCpp: @@ -1383,9 +1383,9 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) = globalError(p.config, x.info, "no 'of' operator available for pure objects") if nilCheck != nil: - r = rfmt(p.module, "(($1) && ($2))", nilCheck, genOfHelper(p, dest, r, x.info)) + r = ropecg(p.module, "(($1) && ($2))", nilCheck, genOfHelper(p, dest, r, x.info)) else: - r = rfmt(p.module, "($1)", genOfHelper(p, dest, r, x.info)) + r = ropecg(p.module, "($1)", genOfHelper(p, dest, r, x.info)) putIntoDest(p, d, x, r, a.storage) proc genOf(p: BProc, n: PNode, d: var TLoc) = @@ -1762,11 +1762,11 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) = if a.kind in {nkStrLit..nkTripleStrLit} and a.strVal == "": initLocExpr(p, e.sons[2], x) putIntoDest(p, d, e, - rfmt(nil, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p))) + ropecg(p.module, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p))) elif b.kind in {nkStrLit..nkTripleStrLit} and b.strVal == "": initLocExpr(p, e.sons[1], x) putIntoDest(p, d, e, - rfmt(nil, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p))) + ropecg(p.module, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p))) else: binaryExpr(p, e, d, "#eqStrings($1, $2)") @@ -1778,7 +1778,7 @@ proc binaryFloatArith(p: BProc, e: PNode, d: var TLoc, m: TMagic) = assert(e.sons[2].typ != nil) initLocExpr(p, e.sons[1], a) initLocExpr(p, e.sons[2], b) - putIntoDest(p, d, e, rfmt(nil, "(($4)($2) $1 ($4)($3))", + putIntoDest(p, d, e, ropecg(p.module, "(($4)($2) $1 ($4)($3))", rope(opr[m]), rdLoc(a), rdLoc(b), getSimpleTypeDesc(p.module, e[1].typ))) if optNaNCheck in p.options: @@ -2295,7 +2295,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = initLocExpr(p, ex, a) of nkAsmStmt: genAsmStmt(p, n) of nkTryStmt: - if p.module.compileToCpp and optNoCppExceptions notin gGlobalOptions: + if p.module.compileToCpp and optNoCppExceptions notin p.config.globalOptions: genTryCpp(p, n, d) else: genTry(p, n, d) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 0ba85488b..1e0a3c818 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -16,7 +16,7 @@ const # above X strings a hash-switch for strings is generated proc registerGcRoot(p: BProc, v: PSym) = - if gSelectedGC in {gcMarkAndSweep, gcGenerational, gcV2, gcRefc} and + if p.config.selectedGC in {gcMarkAndSweep, gcGenerational, gcV2, gcRefc} and containsGarbageCollectedRef(v.loc.t): # we register a specialized marked proc here; this has the advantage # that it works out of the box for thread local storage then :-) @@ -125,7 +125,7 @@ proc endBlock(p: BProc, blockEnd: Rope) = proc endBlock(p: BProc) = let topBlock = p.blocks.len - 1 var blockEnd = if p.blocks[topBlock].label != nil: - rfmt(nil, "} $1: ;$n", p.blocks[topBlock].label) + ropecg(p.module, "} $1: ;$n", p.blocks[topBlock].label) else: ~"}$n" let frameLen = p.blocks[topBlock].frameLen @@ -337,7 +337,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) = for i in countup(1, howManyTrys): let tryStmt = p.nestedTryStmts.pop - if not p.module.compileToCpp or optNoCppExceptions in gGlobalOptions: + if not p.module.compileToCpp or optNoCppExceptions in p.config.globalOptions: # Pop safe points generated by try if not tryStmt.inExcept: linefmt(p, cpsStmts, "#popSafePoint();$n") @@ -356,7 +356,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) = for i in countdown(howManyTrys-1, 0): p.nestedTryStmts.add(stack[i]) - if not p.module.compileToCpp or optNoCppExceptions in gGlobalOptions: + if not p.module.compileToCpp or optNoCppExceptions in p.config.globalOptions: # Pop exceptions that was handled by the # except-blocks we are in for i in countdown(howManyExcepts-1, 0): @@ -571,7 +571,7 @@ proc genRaiseStmt(p: BProc, t: PNode) = var e = rdLoc(a) var typ = skipTypes(t[0].typ, abstractPtrs) genLineDir(p, t) - if isImportedException(typ): + if isImportedException(typ, p.config): lineF(p, cpsStmts, "throw $1;$n", [e]) else: lineCg(p, cpsStmts, "#raiseException((#Exception*)$1, $2);$n", @@ -579,7 +579,7 @@ proc genRaiseStmt(p: BProc, t: PNode) = else: genLineDir(p, t) # reraise the last exception: - if p.module.compileToCpp and optNoCppExceptions notin gGlobalOptions: + if p.module.compileToCpp and optNoCppExceptions notin p.config.globalOptions: line(p, cpsStmts, ~"throw;$n") else: linefmt(p, cpsStmts, "#reraiseException();$n") @@ -1010,7 +1010,7 @@ proc genEmit(p: BProc, t: PNode) = if p.prc == nil: # top level emit pragma? let section = determineSection(t[1]) - genCLineDir(p.module.s[section], t.info) + genCLineDir(p.module.s[section], t.info, p.config) add(p.module.s[section], s) else: genLineDir(p, t) diff --git a/compiler/ccgthreadvars.nim b/compiler/ccgthreadvars.nim index c2ffa9651..da5c624b7 100644 --- a/compiler/ccgthreadvars.nim +++ b/compiler/ccgthreadvars.nim @@ -13,7 +13,7 @@ # included from cgen.nim proc emulatedThreadVars(conf: ConfigRef): bool = - result = {optThreads, optTlsEmulation} <= gGlobalOptions + result = {optThreads, optTlsEmulation} <= conf.globalOptions proc accessThreadLocalVar(p: BProc, s: PSym) = if emulatedThreadVars(p.config) and not p.threadVarAccessed: @@ -46,7 +46,7 @@ proc declareThreadVar(m: BModule, s: PSym, isExtern: bool) = addf(nimtv, "$1 $2;$n", [getTypeDesc(m, s.loc.t), s.loc.r]) else: if isExtern: add(m.s[cfsVars], "extern ") - if optThreads in gGlobalOptions: add(m.s[cfsVars], "NIM_THREADVAR ") + if optThreads in m.config.globalOptions: add(m.s[cfsVars], "NIM_THREADVAR ") add(m.s[cfsVars], getTypeDesc(m, s.loc.t)) addf(m.s[cfsVars], " $1;$n", [s.loc.r]) @@ -57,7 +57,7 @@ proc generateThreadLocalStorage(m: BModule) = proc generateThreadVarsSize(m: BModule) = if nimtv != nil: - let externc = if gCmd == cmdCompileToCpp or + let externc = if m.config.cmd == cmdCompileToCpp or sfCompileToCpp in m.module.flags: "extern \"C\" " else: "" addf(m.s[cfsProcs], diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim index 0e211e239..c265064a1 100644 --- a/compiler/ccgtrav.nim +++ b/compiler/ccgtrav.nim @@ -77,7 +77,7 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) = linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n", i.r, arraySize.rope) let oldLen = p.s(cpsStmts).len - genTraverseProc(c, rfmt(nil, "$1[$2]", accessor, i.r), typ.sons[1]) + genTraverseProc(c, ropecg(c.p.module, "$1[$2]", accessor, i.r), typ.sons[1]) if p.s(cpsStmts).len == oldLen: # do not emit dummy long loops for faster debug builds: p.s(cpsStmts) = oldCode @@ -92,12 +92,12 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) = of tyTuple: let typ = getUniqueType(typ) for i in countup(0, sonsLen(typ) - 1): - genTraverseProc(c, rfmt(nil, "$1.Field$2", accessor, i.rope), typ.sons[i]) + genTraverseProc(c, ropecg(c.p.module, "$1.Field$2", accessor, i.rope), typ.sons[i]) of tyRef, tyString, tySequence: lineCg(p, cpsStmts, c.visitorFrmt, accessor) of tyProc: if typ.callConv == ccClosure: - lineCg(p, cpsStmts, c.visitorFrmt, rfmt(nil, "$1.ClE_0", accessor)) + lineCg(p, cpsStmts, c.visitorFrmt, ropecg(c.p.module, "$1.ClE_0", accessor)) else: discard diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index adebb6cd0..7b44cddad 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -915,7 +915,7 @@ template cgDeclFrmt*(s: PSym): string = s.constraint.strVal proc genProcHeader(m: BModule, prc: PSym): Rope = var rettype, params: Rope - genCLineDir(result, prc.info) + genCLineDir(result, prc.info, m.config) # using static is needed for inline procs if lfExportLib in prc.loc.flags: if isHeaderFile in m.flags: @@ -1239,7 +1239,7 @@ proc genTypeInfo(m: BModule, t: PType; info: TLineInfo): Rope = genTupleInfo(m, x, x, result, info) of tySequence, tyRef, tyOptAsRef: genTypeInfoAux(m, t, t, result, info) - if gSelectedGC >= gcMarkAndSweep: + if m.config.selectedGC >= gcMarkAndSweep: let markerProc = genTraverseProc(m, origType, sig) addf(m.s[cfsTypeInit3], "$1.marker = $2;$n", [result, markerProc]) of tyPtr, tyRange: genTypeInfoAux(m, t, t, result, info) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 3a5d66762..133e86cea 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -93,6 +93,7 @@ proc useHeader(m: BModule, sym: PSym) = proc cgsym(m: BModule, name: string): Rope proc ropecg(m: BModule, frmt: FormatStr, args: varargs[Rope]): Rope = + assert m != nil var i = 0 var length = len(frmt) result = nil @@ -119,7 +120,7 @@ proc ropecg(m: BModule, frmt: FormatStr, args: varargs[Rope]): Rope = internalError(m.config, "ropes: invalid format string $" & $j) add(result, args[j-1]) of 'n': - if optLineDir notin gOptions: add(result, rnl) + if optLineDir notin m.config.options: add(result, rnl) inc(i) of 'N': add(result, rnl) @@ -146,9 +147,6 @@ proc ropecg(m: BModule, frmt: FormatStr, args: varargs[Rope]): Rope = if i - 1 >= start: add(result, substr(frmt, start, i - 1)) -template rfmt(m: BModule, fmt: string, args: varargs[Rope]): untyped = - ropecg(m, fmt, args) - proc indentLine(p: BProc, r: Rope): Rope = result = r for i in countup(0, p.blocks.len-1): @@ -188,14 +186,14 @@ proc safeLineNm(info: TLineInfo): int = result = toLinenumber(info) if result < 0: result = 0 # negative numbers are not allowed in #line -proc genCLineDir(r: var Rope, filename: string, line: int) = +proc genCLineDir(r: var Rope, filename: string, line: int; conf: ConfigRef) = assert line >= 0 - if optLineDir in gOptions: + if optLineDir in conf.options: addf(r, "$N#line $2 $1$N", [rope(makeSingleLineCString(filename)), rope(line)]) -proc genCLineDir(r: var Rope, info: TLineInfo) = - genCLineDir(r, info.toFullPath, info.safeLineNm) +proc genCLineDir(r: var Rope, info: TLineInfo; conf: ConfigRef) = + genCLineDir(r, info.toFullPath, info.safeLineNm, conf) proc freshLineInfo(p: BProc; info: TLineInfo): bool = if p.lastLineInfo.line != info.line or @@ -212,9 +210,9 @@ proc genLineDir(p: BProc, t: PNode) = tt = tt.sons[1] let line = tt.info.safeLineNm - if optEmbedOrigSrc in gGlobalOptions: + if optEmbedOrigSrc in p.config.globalOptions: add(p.s(cpsStmts), ~"//" & sourceLine(p.config, tt.info) & rnl) - genCLineDir(p.s(cpsStmts), tt.info.toFullPath, line) + genCLineDir(p.s(cpsStmts), tt.info.toFullPath, line, p.config) if ({optStackTrace, optEndb} * p.options == {optStackTrace, optEndb}) and (p.prc == nil or sfPure notin p.prc.flags): if freshLineInfo(p, tt.info): @@ -235,7 +233,7 @@ proc emulatedThreadVars(conf: ConfigRef): bool {.inline.} proc genProc(m: BModule, prc: PSym) template compileToCpp(m: BModule): untyped = - gCmd == cmdCompileToCpp or sfCompileToCpp in m.module.flags + m.config.cmd == cmdCompileToCpp or sfCompileToCpp in m.module.flags proc getTempName(m: BModule): Rope = result = m.tmpBase & rope(m.labels) @@ -416,7 +414,7 @@ proc assignLocalVar(p: BProc, n: PNode) = #assert(s.loc.k == locNone) # not yet assigned # this need not be fulfilled for inline procs; they are regenerated # for each module that uses them! - let nl = if optLineDir in gOptions: "" else: tnl + let nl = if optLineDir in p.config.options: "" else: tnl let decl = localVarDecl(p, n) & ";" & nl line(p, cpsLocals, decl) localDebugInfo(p, n.sym) @@ -510,24 +508,24 @@ proc initFrame(p: BProc, procname, filename: Rope): Rope = discard cgsym(p.module, "nimFrame") if p.maxFrameLen > 0: discard cgsym(p.module, "VarSlot") - result = rfmt(nil, "\tnimfrs_($1, $2, $3, $4);$n", + result = ropecg(p.module, "\tnimfrs_($1, $2, $3, $4);$n", procname, filename, p.maxFrameLen.rope, p.blocks[0].frameLen.rope) else: - result = rfmt(nil, "\tnimfr_($1, $2);$n", procname, filename) + result = ropecg(p.module, "\tnimfr_($1, $2);$n", procname, filename) proc initFrameNoDebug(p: BProc; frame, procname, filename: Rope; line: int): Rope = discard cgsym(p.module, "nimFrame") addf(p.blocks[0].sections[cpsLocals], "TFrame $1;$n", [frame]) - result = rfmt(nil, "\t$1.procname = $2; $1.filename = $3; " & + result = ropecg(p.module, "\t$1.procname = $2; $1.filename = $3; " & " $1.line = $4; $1.len = -1; nimFrame(&$1);$n", frame, procname, filename, rope(line)) proc deinitFrameNoDebug(p: BProc; frame: Rope): Rope = - result = rfmt(p.module, "\t#popFrameOfAddr(&$1);$n", frame) + result = ropecg(p.module, "\t#popFrameOfAddr(&$1);$n", frame) proc deinitFrame(p: BProc): Rope = - result = rfmt(p.module, "\t#popFrame();$n") + result = ropecg(p.module, "\t#popFrame();$n") include ccgexprs @@ -741,7 +739,7 @@ proc genProcAux(m: BModule, prc: PSym) = assignLocalVar(p, resNode) assert(res.loc.r != nil) initLocalVar(p, res, immediateAsgn=false) - returnStmt = rfmt(nil, "\treturn $1;$n", rdLoc(res.loc)) + returnStmt = ropecg(p.module, "\treturn $1;$n", rdLoc(res.loc)) else: fillResult(resNode) assignParam(p, res) @@ -763,10 +761,10 @@ proc genProcAux(m: BModule, prc: PSym) = if sfPure in prc.flags: if hasDeclspec in extccomp.CC[extccomp.cCompiler].props: header = "__declspec(naked) " & header - generatedProc = rfmt(nil, "$N$1 {$n$2$3$4}$N$N", + generatedProc = ropecg(p.module, "$N$1 {$n$2$3$4}$N$N", header, p.s(cpsLocals), p.s(cpsInit), p.s(cpsStmts)) else: - generatedProc = rfmt(nil, "$N$1 {$N", header) + generatedProc = ropecg(p.module, "$N$1 {$N", header) add(generatedProc, initGCFrame(p)) if optStackTrace in prc.options: add(generatedProc, p.s(cpsLocals)) @@ -790,10 +788,10 @@ proc genProcAux(m: BModule, prc: PSym) = proc requiresExternC(m: BModule; sym: PSym): bool {.inline.} = result = (sfCompileToCpp in m.module.flags and sfCompileToCpp notin sym.getModule().flags and - gCmd != cmdCompileToCpp) or ( + m.config.cmd != cmdCompileToCpp) or ( sym.flags * {sfImportc, sfInfixCall, sfCompilerProc} == {sfImportc} and sym.magic == mNone and - gCmd == cmdCompileToCpp) + m.config.cmd == cmdCompileToCpp) proc genProcPrototype(m: BModule, sym: PSym) = useHeader(m, sym) @@ -801,7 +799,7 @@ proc genProcPrototype(m: BModule, sym: PSym) = if lfDynamicLib in sym.loc.flags: if getModule(sym).id != m.module.id and not containsOrIncl(m.declaredThings, sym.id): - add(m.s[cfsVars], rfmt(nil, "extern $1 $2;$n", + add(m.s[cfsVars], ropecg(m, "extern $1 $2;$n", getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym))) elif not containsOrIncl(m.declaredProtos, sym.id): var header = genProcHeader(m, sym) @@ -813,7 +811,7 @@ proc genProcPrototype(m: BModule, sym: PSym) = header.add(" __attribute__((naked))") if sfNoReturn in sym.flags and hasAttribute in CC[cCompiler].props: header.add(" __attribute__((noreturn))") - add(m.s[cfsProcHeaders], rfmt(nil, "$1;$n", header)) + add(m.s[cfsProcHeaders], ropecg(m, "$1;$n", header)) proc genProcNoForward(m: BModule, prc: PSym) = if lfImportCompilerProc in prc.loc.flags: @@ -919,14 +917,14 @@ proc genVarPrototype(m: BModule, n: PNode) = if sfVolatile in sym.flags: add(m.s[cfsVars], " volatile") addf(m.s[cfsVars], " $1;$n", [sym.loc.r]) -proc addIntTypes(result: var Rope) {.inline.} = +proc addIntTypes(result: var Rope; conf: ConfigRef) {.inline.} = addf(result, "#define NIM_NEW_MANGLING_RULES" & tnl & "#define NIM_INTBITS $1" & tnl, [ platform.CPU[targetCPU].intSize.rope]) - if useNimNamespace : result.add("#define USE_NIM_NAMESPACE" & tnl) + if optUseNimNamespace in conf.globalOptions: result.add("#define USE_NIM_NAMESPACE" & tnl) proc getCopyright(conf: ConfigRef; cfile: Cfile): Rope = - if optCompileOnly in gGlobalOptions: + if optCompileOnly in conf.globalOptions: result = ("/* Generated by Nim Compiler v$1 */$N" & "/* (c) " & copyrightYear & " Andreas Rumpf */$N" & "/* The generated code is subject to the original license. */$N") % @@ -945,7 +943,7 @@ proc getCopyright(conf: ConfigRef; cfile: Cfile): Rope = proc getFileHeader(conf: ConfigRef; cfile: Cfile): Rope = result = getCopyright(conf, cfile) - addIntTypes(result) + addIntTypes(result, conf) proc genFilenames(m: BModule): Rope = discard cgsym(m, "dbgRegisterFilename") @@ -1050,8 +1048,8 @@ proc genMainProc(m: BModule) = var nimMain, otherMain: FormatStr if platform.targetOS == osWindows and - gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}: - if optGenGuiApp in gGlobalOptions: + m.config.globalOptions * {optGenGuiApp, optGenDynLib} != {}: + if optGenGuiApp in m.config.globalOptions: nimMain = WinNimMain otherMain = WinCMain else: @@ -1061,7 +1059,7 @@ proc genMainProc(m: BModule) = elif platform.targetOS == osGenode: nimMain = GenodeNimMain otherMain = ComponentConstruct - elif optGenDynLib in gGlobalOptions: + elif optGenDynLib in m.config.globalOptions: nimMain = PosixNimDllMain otherMain = PosixCDllMain elif platform.targetOS == osStandalone: @@ -1071,11 +1069,11 @@ proc genMainProc(m: BModule) = nimMain = PosixNimMain otherMain = PosixCMain if m.g.breakpoints != nil: discard cgsym(m, "dbgRegisterBreakpoint") - if optEndb in gOptions: + if optEndb in m.config.options: m.g.breakpoints.add(m.genFilenames) let initStackBottomCall = - if platform.targetOS == osStandalone or gSelectedGC == gcNone: "".rope + if platform.targetOS == osStandalone or m.config.selectedGC == gcNone: "".rope else: ropecg(m, "\t#initStackBottomWith((void *)&inner);$N") inc(m.labels) appcg(m, m.s[cfsProcs], PreMainBody, [ @@ -1088,12 +1086,12 @@ proc genMainProc(m: BModule) = appcg(m, m.s[cfsProcs], nimMain, [m.g.mainModInit, initStackBottomCall, rope(m.labels)]) - if optNoMain notin gGlobalOptions: - if useNimNamespace: + if optNoMain notin m.config.globalOptions: + if optUseNimNamespace in m.config.globalOptions: m.s[cfsProcs].add closeNamespaceNim() & "using namespace Nim;" & tnl appcg(m, m.s[cfsProcs], otherMain, []) - if useNimNamespace: m.s[cfsProcs].add openNamespaceNim() + if optUseNimNamespace in m.config.globalOptions: m.s[cfsProcs].add openNamespaceNim() proc getSomeInitName(m: PSym, suffix: string): Rope = assert m.kind == skModule @@ -1201,9 +1199,10 @@ proc genModule(m: BModule, cfile: Cfile): Rope = add(result, genSectionStart(i, m.config)) add(result, m.s[i]) add(result, genSectionEnd(i, m.config)) - if useNimNamespace and i == cfsHeaders: result.add openNamespaceNim() + if optUseNimNamespace in m.config.globalOptions and i == cfsHeaders: + result.add openNamespaceNim() add(result, m.s[cfsInitProc]) - if useNimNamespace: result.add closeNamespaceNim() + if optUseNimNamespace in m.config.globalOptions: result.add closeNamespaceNim() proc newPreInitProc(m: BModule): BProc = result = newProc(nil, m) @@ -1216,10 +1215,12 @@ proc newPostInitProc(m: BModule): BProc = result.labels = 200_000 proc initProcOptions(m: BModule): TOptions = - if sfSystemModule in m.module.flags: gOptions-{optStackTrace} else: gOptions + let opts = m.config.options + if sfSystemModule in m.module.flags: opts-{optStackTrace} else: opts proc rawNewModule(g: BModuleList; module: PSym, filename: string): BModule = new(result) + result.g = g result.tmpBase = rope("TM" & $hashOwner(module) & "_") result.headerFiles = @[] result.declaredThings = initIntSet() @@ -1240,14 +1241,13 @@ proc rawNewModule(g: BModuleList; module: PSym, filename: string): BModule = result.forwardedProcs = @[] result.typeNodesName = getTempName(result) result.nimTypesName = getTempName(result) - result.g = g # no line tracing for the init sections of the system module so that we # don't generate a TFrame which can confuse the stack botton initialization: if sfSystemModule in module.flags: incl result.flags, preventStackTrace excl(result.preInitProc.options, optStackTrace) excl(result.postInitProc.options, optStackTrace) - let ndiName = if optCDebug in gGlobalOptions: changeFileExt(completeCFilePath(g.config, filename), "ndi") + let ndiName = if optCDebug in g.config.globalOptions: changeFileExt(completeCFilePath(g.config, filename), "ndi") else: "" open(result.ndi, ndiName) @@ -1316,7 +1316,7 @@ template injectG() {.dirty.} = proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext = injectG() result = newModule(g, module) - if optGenIndex in gGlobalOptions and g.generatedHeader == nil: + if optGenIndex in graph.config.globalOptions and g.generatedHeader == nil: let f = if graph.config.headerFile.len > 0: graph.config.headerFile else: graph.config.projectFull g.generatedHeader = rawNewModule(g, module, @@ -1331,7 +1331,7 @@ proc writeHeader(m: BModule) = var guard = "__$1__" % [m.filename.splitFile.name.rope] result.addf("#ifndef $1$n#define $1$n", [guard]) - addIntTypes(result) + addIntTypes(result, m.config) generateHeaders(m) generateThreadLocalStorage(m) @@ -1339,20 +1339,20 @@ proc writeHeader(m: BModule) = add(result, genSectionStart(i, m.config)) add(result, m.s[i]) add(result, genSectionEnd(i, m.config)) - if useNimNamespace and i == cfsHeaders: result.add openNamespaceNim() + if optUseNimNamespace in m.config.globalOptions and i == cfsHeaders: result.add openNamespaceNim() add(result, m.s[cfsInitProc]) - if optGenDynLib in gGlobalOptions: + if optGenDynLib in m.config.globalOptions: result.add("N_LIB_IMPORT ") result.addf("N_CDECL(void, NimMain)(void);$n", []) - if useNimNamespace: result.add closeNamespaceNim() + if optUseNimNamespace in m.config.globalOptions: result.add closeNamespaceNim() result.addf("#endif /* $1 */$n", [guard]) writeRope(result, m.filename) proc getCFile(m: BModule): string = let ext = if m.compileToCpp: ".cpp" - elif gCmd == cmdCompileToOC or sfCompileToObjC in m.module.flags: ".m" + elif m.config.cmd == cmdCompileToOC or sfCompileToObjC in m.module.flags: ".m" else: ".c" result = changeFileExt(completeCFilePath(m.config, withPackageName(m.config, m.cfilename)), ext) @@ -1368,7 +1368,7 @@ proc myProcess(b: PPassContext, n: PNode): PNode = var m = BModule(b) if passes.skipCodegen(m.config, n): return m.initProc.options = initProcOptions(m) - softRnl = if optLineDir in gOptions: noRnl else: rnl + softRnl = if optLineDir in m.config.options: noRnl else: rnl genStmts(m.initProc, n) proc finishModule(m: BModule) = @@ -1387,7 +1387,7 @@ proc finishModule(m: BModule) = proc shouldRecompile(m: BModule; code: Rope, cfile: Cfile): bool = result = true - if optForceFullMake notin gGlobalOptions: + if optForceFullMake notin m.config.globalOptions: if not equalsFile(code, cfile.cname): if isDefined(m.config, "nimdiff"): if fileExists(cfile.cname): @@ -1412,7 +1412,7 @@ proc writeModule(m: BModule, pending: bool) = # generate code for the init statements of the module: let cfile = getCFile(m) - if m.rd == nil or optForceFullMake in gGlobalOptions: + if m.rd == nil or optForceFullMake in m.config.globalOptions: genInitCode(m) finishTypeDescriptions(m) if sfMainModule in m.module.flags: @@ -1423,7 +1423,7 @@ proc writeModule(m: BModule, pending: bool) = var cf = Cfile(cname: cfile, obj: completeCFilePath(m.config, toObjFile(m.config, cfile)), flags: {}) var code = genModule(m, cf) when hasTinyCBackend: - if gCmd == cmdRun: + if conf.cmd == cmdRun: tccgen.compileCCode($code) return diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim index 0c310dd7d..ce3fc2f90 100644 --- a/compiler/cgendata.nim +++ b/compiler/cgendata.nim @@ -170,7 +170,7 @@ proc newProc*(prc: PSym, module: BModule): BProc = result.prc = prc result.module = module if prc != nil: result.options = prc.options - else: result.options = gOptions + else: result.options = module.config.options newSeq(result.blocks, 1) result.nestedTryStmts = @[] result.finallySafePoints = @[] diff --git a/compiler/commands.nim b/compiler/commands.nim index 328dc2f02..09f63f0f5 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -61,49 +61,49 @@ proc getCommandLineDesc(): string = CPU[platform.hostCPU].name, CompileDate]) & Usage -proc helpOnError(pass: TCmdLinePass) = +proc helpOnError(conf: ConfigRef; pass: TCmdLinePass) = if pass == passCmd1: - msgWriteln(getCommandLineDesc(), {msgStdout}) + msgWriteln(conf, getCommandLineDesc(), {msgStdout}) msgQuit(0) -proc writeAdvancedUsage(pass: TCmdLinePass) = +proc writeAdvancedUsage(conf: ConfigRef; pass: TCmdLinePass) = if pass == passCmd1: - msgWriteln(`%`(HelpMessage, [VersionAsString, + msgWriteln(conf, (HelpMessage % [VersionAsString, platform.OS[platform.hostOS].name, CPU[platform.hostCPU].name, CompileDate]) & AdvancedUsage, {msgStdout}) msgQuit(0) -proc writeFullhelp(pass: TCmdLinePass) = +proc writeFullhelp(conf: ConfigRef; pass: TCmdLinePass) = if pass == passCmd1: - msgWriteln(`%`(HelpMessage, [VersionAsString, + msgWriteln(conf, `%`(HelpMessage, [VersionAsString, platform.OS[platform.hostOS].name, CPU[platform.hostCPU].name, CompileDate]) & Usage & AdvancedUsage, {msgStdout}) msgQuit(0) -proc writeVersionInfo(pass: TCmdLinePass) = +proc writeVersionInfo(conf: ConfigRef; pass: TCmdLinePass) = if pass == passCmd1: - msgWriteln(`%`(HelpMessage, [VersionAsString, + msgWriteln(conf, `%`(HelpMessage, [VersionAsString, platform.OS[platform.hostOS].name, CPU[platform.hostCPU].name, CompileDate]), {msgStdout}) const gitHash = gorge("git log -n 1 --format=%H").strip when gitHash.len == 40: - msgWriteln("git hash: " & gitHash, {msgStdout}) + msgWriteln(conf, "git hash: " & gitHash, {msgStdout}) - msgWriteln("active boot switches:" & usedRelease & + msgWriteln(conf, "active boot switches:" & usedRelease & usedTinyC & usedGnuReadline & usedNativeStacktrace & usedFFI & usedBoehm & usedMarkAndSweep & usedGenerational & usedGoGC & usedNoGC, {msgStdout}) msgQuit(0) -proc writeCommandLineUsage*(helpWritten: var bool) = +proc writeCommandLineUsage*(conf: ConfigRef; helpWritten: var bool) = if not helpWritten: - msgWriteln(getCommandLineDesc(), {msgStdout}) + msgWriteln(conf, getCommandLineDesc(), {msgStdout}) helpWritten = true proc addPrefix(switch: string): string = @@ -137,24 +137,24 @@ proc splitSwitch(conf: ConfigRef; switch: string, cmd, arg: var string, pass: TC proc processOnOffSwitch(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass, info: TLineInfo) = case arg.normalize - of "on": gOptions = gOptions + op - of "off": gOptions = gOptions - op + of "on": conf.options = conf.options + op + of "off": conf.options = conf.options - op else: localError(conf, info, errOnOrOffExpectedButXFound % arg) proc processOnOffSwitchOrList(conf: ConfigRef; op: TOptions, arg: string, pass: TCmdLinePass, info: TLineInfo): bool = result = false case arg.normalize - of "on": gOptions = gOptions + op - of "off": gOptions = gOptions - op + of "on": conf.options = conf.options + op + of "off": conf.options = conf.options - op of "list": result = true else: localError(conf, info, errOnOffOrListExpectedButXFound % arg) proc processOnOffSwitchG(conf: ConfigRef; op: TGlobalOptions, arg: string, pass: TCmdLinePass, info: TLineInfo) = case arg.normalize - of "on": gGlobalOptions = gGlobalOptions + op - of "off": gGlobalOptions = gGlobalOptions - op + of "on": conf.globalOptions = conf.globalOptions + op + of "off": conf.globalOptions = conf.globalOptions - op else: localError(conf, info, errOnOrOffExpectedButXFound % arg) proc expectArg(conf: ConfigRef; switch, arg: string, pass: TCmdLinePass, info: TLineInfo) = @@ -211,30 +211,30 @@ proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo case switch.normalize of "gc": case arg.normalize - of "boehm": result = gSelectedGC == gcBoehm - of "refc": result = gSelectedGC == gcRefc - of "v2": result = gSelectedGC == gcV2 - of "markandsweep": result = gSelectedGC == gcMarkAndSweep - of "generational": result = gSelectedGC == gcGenerational - of "go": result = gSelectedGC == gcGo - of "none": result = gSelectedGC == gcNone - of "stack", "regions": result = gSelectedGC == gcRegions + of "boehm": result = conf.selectedGC == gcBoehm + of "refc": result = conf.selectedGC == gcRefc + of "v2": result = conf.selectedGC == gcV2 + of "markandsweep": result = conf.selectedGC == gcMarkAndSweep + of "generational": result = conf.selectedGC == gcGenerational + of "go": result = conf.selectedGC == gcGo + of "none": result = conf.selectedGC == gcNone + of "stack", "regions": result = conf.selectedGC == gcRegions else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg) of "opt": case arg.normalize - of "speed": result = contains(gOptions, optOptimizeSpeed) - of "size": result = contains(gOptions, optOptimizeSize) - of "none": result = gOptions * {optOptimizeSpeed, optOptimizeSize} == {} + of "speed": result = contains(conf.options, optOptimizeSpeed) + of "size": result = contains(conf.options, optOptimizeSize) + of "none": result = conf.options * {optOptimizeSpeed, optOptimizeSize} == {} else: localError(conf, info, errNoneSpeedOrSizeExpectedButXFound % arg) - of "verbosity": result = $gVerbosity == arg + of "verbosity": result = $conf.verbosity == arg of "app": case arg.normalize - of "gui": result = contains(gGlobalOptions, optGenGuiApp) - of "console": result = not contains(gGlobalOptions, optGenGuiApp) - of "lib": result = contains(gGlobalOptions, optGenDynLib) and - not contains(gGlobalOptions, optGenGuiApp) - of "staticlib": result = contains(gGlobalOptions, optGenStaticLib) and - not contains(gGlobalOptions, optGenGuiApp) + of "gui": result = contains(conf.globalOptions, optGenGuiApp) + of "console": result = not contains(conf.globalOptions, optGenGuiApp) + of "lib": result = contains(conf.globalOptions, optGenDynLib) and + not contains(conf.globalOptions, optGenGuiApp) + of "staticlib": result = contains(conf.globalOptions, optGenStaticLib) and + not contains(conf.globalOptions, optGenGuiApp) else: localError(conf, info, errGuiConsoleOrLibExpectedButXFound % arg) of "dynliboverride": result = isDynlibOverride(conf, arg) @@ -242,42 +242,42 @@ proc testCompileOptionArg*(conf: ConfigRef; switch, arg: string, info: TLineInfo proc testCompileOption*(conf: ConfigRef; switch: string, info: TLineInfo): bool = case switch.normalize - of "debuginfo": result = contains(gGlobalOptions, optCDebug) - of "compileonly", "c": result = contains(gGlobalOptions, optCompileOnly) - of "nolinking": result = contains(gGlobalOptions, optNoLinking) - of "nomain": result = contains(gGlobalOptions, optNoMain) - of "forcebuild", "f": result = contains(gGlobalOptions, optForceFullMake) - of "warnings", "w": result = contains(gOptions, optWarns) - of "hints": result = contains(gOptions, optHints) - of "threadanalysis": result = contains(gGlobalOptions, optThreadAnalysis) - of "stacktrace": result = contains(gOptions, optStackTrace) - of "linetrace": result = contains(gOptions, optLineTrace) - of "debugger": result = contains(gOptions, optEndb) - of "profiler": result = contains(gOptions, optProfiler) - of "memtracker": result = contains(gOptions, optMemTracker) - of "checks", "x": result = gOptions * ChecksOptions == ChecksOptions + of "debuginfo": result = contains(conf.globalOptions, optCDebug) + of "compileonly", "c": result = contains(conf.globalOptions, optCompileOnly) + of "nolinking": result = contains(conf.globalOptions, optNoLinking) + of "nomain": result = contains(conf.globalOptions, optNoMain) + of "forcebuild", "f": result = contains(conf.globalOptions, optForceFullMake) + of "warnings", "w": result = contains(conf.options, optWarns) + of "hints": result = contains(conf.options, optHints) + of "threadanalysis": result = contains(conf.globalOptions, optThreadAnalysis) + of "stacktrace": result = contains(conf.options, optStackTrace) + of "linetrace": result = contains(conf.options, optLineTrace) + of "debugger": result = contains(conf.options, optEndb) + of "profiler": result = contains(conf.options, optProfiler) + of "memtracker": result = contains(conf.options, optMemTracker) + of "checks", "x": result = conf.options * ChecksOptions == ChecksOptions of "floatchecks": - result = gOptions * {optNaNCheck, optInfCheck} == {optNaNCheck, optInfCheck} - of "infchecks": result = contains(gOptions, optInfCheck) - of "nanchecks": result = contains(gOptions, optNaNCheck) - of "nilchecks": result = contains(gOptions, optNilCheck) - of "objchecks": result = contains(gOptions, optObjCheck) - of "fieldchecks": result = contains(gOptions, optFieldCheck) - of "rangechecks": result = contains(gOptions, optRangeCheck) - of "boundchecks": result = contains(gOptions, optBoundsCheck) - of "overflowchecks": result = contains(gOptions, optOverflowCheck) - of "movechecks": result = contains(gOptions, optMoveCheck) - of "linedir": result = contains(gOptions, optLineDir) - of "assertions", "a": result = contains(gOptions, optAssert) - of "run", "r": result = contains(gGlobalOptions, optRun) - of "symbolfiles": result = gSymbolFiles != disabledSf - of "genscript": result = contains(gGlobalOptions, optGenScript) - of "threads": result = contains(gGlobalOptions, optThreads) - of "taintmode": result = contains(gGlobalOptions, optTaintMode) - of "tlsemulation": result = contains(gGlobalOptions, optTlsEmulation) - of "implicitstatic": result = contains(gOptions, optImplicitStatic) - of "patterns": result = contains(gOptions, optPatterns) - of "excessivestacktrace": result = contains(gGlobalOptions, optExcessiveStackTrace) + result = conf.options * {optNaNCheck, optInfCheck} == {optNaNCheck, optInfCheck} + of "infchecks": result = contains(conf.options, optInfCheck) + of "nanchecks": result = contains(conf.options, optNaNCheck) + of "nilchecks": result = contains(conf.options, optNilCheck) + of "objchecks": result = contains(conf.options, optObjCheck) + of "fieldchecks": result = contains(conf.options, optFieldCheck) + of "rangechecks": result = contains(conf.options, optRangeCheck) + of "boundchecks": result = contains(conf.options, optBoundsCheck) + of "overflowchecks": result = contains(conf.options, optOverflowCheck) + of "movechecks": result = contains(conf.options, optMoveCheck) + of "linedir": result = contains(conf.options, optLineDir) + of "assertions", "a": result = contains(conf.options, optAssert) + of "run", "r": result = contains(conf.globalOptions, optRun) + of "symbolfiles": result = conf.symbolFiles != disabledSf + of "genscript": result = contains(conf.globalOptions, optGenScript) + of "threads": result = contains(conf.globalOptions, optThreads) + of "taintmode": result = contains(conf.globalOptions, optTaintMode) + of "tlsemulation": result = contains(conf.globalOptions, optTlsEmulation) + of "implicitstatic": result = contains(conf.options, optImplicitStatic) + of "patterns": result = contains(conf.options, optPatterns) + of "excessivestacktrace": result = contains(conf.globalOptions, optExcessiveStackTrace) else: invalidCmdLineOption(conf, passCmd1, switch, info) proc processPath(conf: ConfigRef; path: string, info: TLineInfo, @@ -353,7 +353,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; addPath(conf, if pass == passPP: processCfgPath(conf, arg, info) else: processPath(conf, arg, info), info) of "nimblepath", "babelpath": # keep the old name for compat - if pass in {passCmd2, passPP} and not options.gNoNimblePath: + if pass in {passCmd2, passPP} and optNoNimblePath notin conf.globalOptions: expectArg(conf, switch, arg, pass, info) var path = processPath(conf, arg, info, notRelativeToProj=true) let nimbleDir = getEnv("NIMBLE_DIR") @@ -405,49 +405,49 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; if pass in {passCmd2, passPP}: addExternalFileToLink(conf, arg) of "debuginfo": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optCDebug) + incl(conf.globalOptions, optCDebug) of "embedsrc": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optEmbedOrigSrc) + incl(conf.globalOptions, optEmbedOrigSrc) of "compileonly", "c": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optCompileOnly) + incl(conf.globalOptions, optCompileOnly) of "nolinking": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optNoLinking) + incl(conf.globalOptions, optNoLinking) of "nomain": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optNoMain) + incl(conf.globalOptions, optNoMain) of "forcebuild", "f": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optForceFullMake) + incl(conf.globalOptions, optForceFullMake) of "project": expectNoArg(conf, switch, arg, pass, info) - gWholeProject = true + incl conf.globalOptions, optWholeProject of "gc": expectArg(conf, switch, arg, pass, info) case arg.normalize of "boehm": - gSelectedGC = gcBoehm + conf.selectedGC = gcBoehm defineSymbol(conf.symbols, "boehmgc") of "refc": - gSelectedGC = gcRefc + conf.selectedGC = gcRefc of "v2": - gSelectedGC = gcV2 + conf.selectedGC = gcV2 of "markandsweep": - gSelectedGC = gcMarkAndSweep + conf.selectedGC = gcMarkAndSweep defineSymbol(conf.symbols, "gcmarkandsweep") of "generational": - gSelectedGC = gcGenerational + conf.selectedGC = gcGenerational defineSymbol(conf.symbols, "gcgenerational") of "go": - gSelectedGC = gcGo + conf.selectedGC = gcGo defineSymbol(conf.symbols, "gogc") of "none": - gSelectedGC = gcNone + conf.selectedGC = gcNone defineSymbol(conf.symbols, "nogc") of "stack", "regions": - gSelectedGC= gcRegions + conf.selectedGC= gcRegions defineSymbol(conf.symbols, "gcregions") else: localError(conf, info, errNoneBoehmRefcExpectedButXFound % arg) of "warnings", "w": @@ -463,29 +463,29 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "debugger": case arg.normalize of "on", "endb": - gOptions.incl optEndb + conf.options.incl optEndb defineSymbol(conf.symbols, "endb") of "off": - gOptions.excl optEndb + conf.options.excl optEndb undefSymbol(conf.symbols, "endb") of "native", "gdb": - incl(gGlobalOptions, optCDebug) - gOptions = gOptions + {optLineDir} - {optEndb} + incl(conf.globalOptions, optCDebug) + conf.options = conf.options + {optLineDir} - {optEndb} defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing undefSymbol(conf.symbols, "endb") else: localError(conf, info, "expected endb|gdb but found " & arg) of "profiler": processOnOffSwitch(conf, {optProfiler}, arg, pass, info) - if optProfiler in gOptions: defineSymbol(conf.symbols, "profiler") + if optProfiler in conf.options: defineSymbol(conf.symbols, "profiler") else: undefSymbol(conf.symbols, "profiler") of "memtracker": processOnOffSwitch(conf, {optMemTracker}, arg, pass, info) - if optMemTracker in gOptions: defineSymbol(conf.symbols, "memtracker") + if optMemTracker in conf.options: defineSymbol(conf.symbols, "memtracker") else: undefSymbol(conf.symbols, "memtracker") of "hotcodereloading": processOnOffSwitch(conf, {optHotCodeReloading}, arg, pass, info) - if optHotCodeReloading in gOptions: defineSymbol(conf.symbols, "hotcodereloading") + if optHotCodeReloading in conf.options: defineSymbol(conf.symbols, "hotcodereloading") else: undefSymbol(conf.symbols, "hotcodereloading") of "oldnewlines": case arg.normalize @@ -515,7 +515,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "deadcodeelim": discard # deprecated, dead code elim always on of "threads": processOnOffSwitchG(conf, {optThreads}, arg, pass, info) - #if optThreads in gGlobalOptions: incl(conf.notes, warnGcUnsafe) + #if optThreads in conf.globalOptions: incl(conf.notes, warnGcUnsafe) of "tlsemulation": processOnOffSwitchG(conf, {optTlsEmulation}, arg, pass, info) of "taintmode": processOnOffSwitchG(conf, {optTaintMode}, arg, pass, info) of "implicitstatic": @@ -526,34 +526,34 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; expectArg(conf, switch, arg, pass, info) case arg.normalize of "speed": - incl(gOptions, optOptimizeSpeed) - excl(gOptions, optOptimizeSize) + incl(conf.options, optOptimizeSpeed) + excl(conf.options, optOptimizeSize) of "size": - excl(gOptions, optOptimizeSpeed) - incl(gOptions, optOptimizeSize) + excl(conf.options, optOptimizeSpeed) + incl(conf.options, optOptimizeSize) of "none": - excl(gOptions, optOptimizeSpeed) - excl(gOptions, optOptimizeSize) + excl(conf.options, optOptimizeSpeed) + excl(conf.options, optOptimizeSize) else: localError(conf, info, errNoneSpeedOrSizeExpectedButXFound % arg) of "app": expectArg(conf, switch, arg, pass, info) case arg.normalize of "gui": - incl(gGlobalOptions, optGenGuiApp) + incl(conf.globalOptions, optGenGuiApp) defineSymbol(conf.symbols, "executable") defineSymbol(conf.symbols, "guiapp") of "console": - excl(gGlobalOptions, optGenGuiApp) + excl(conf.globalOptions, optGenGuiApp) defineSymbol(conf.symbols, "executable") defineSymbol(conf.symbols, "consoleapp") of "lib": - incl(gGlobalOptions, optGenDynLib) - excl(gGlobalOptions, optGenGuiApp) + incl(conf.globalOptions, optGenDynLib) + excl(conf.globalOptions, optGenGuiApp) defineSymbol(conf.symbols, "library") defineSymbol(conf.symbols, "dll") of "staticlib": - incl(gGlobalOptions, optGenStaticLib) - excl(gGlobalOptions, optGenGuiApp) + incl(conf.globalOptions, optGenStaticLib) + excl(conf.globalOptions, optGenGuiApp) defineSymbol(conf.symbols, "library") defineSymbol(conf.symbols, "staticlib") else: localError(conf, info, errGuiConsoleOrLibExpectedButXFound % arg) @@ -574,7 +574,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; if pass in {passCmd2, passPP}: cLinkedLibs.add processPath(conf, arg, info) of "header": if conf != nil: conf.headerFile = arg - incl(gGlobalOptions, optGenIndex) + incl(conf.globalOptions, optGenIndex) of "index": processOnOffSwitchG(conf, {optGenIndex}, arg, pass, info) of "import": @@ -585,10 +585,10 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; if pass in {passCmd2, passPP}: conf.implicitIncludes.add arg of "listcmd": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optListCmd) + incl(conf.globalOptions, optListCmd) of "genmapping": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optGenMapping) + incl(conf.globalOptions, optGenMapping) of "os": expectArg(conf, switch, arg, pass, info) if pass in {passCmd1, passPP}: @@ -605,53 +605,53 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; setTarget(targetOS, cpu) of "run", "r": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optRun) + incl(conf.globalOptions, optRun) of "verbosity": expectArg(conf, switch, arg, pass, info) - gVerbosity = parseInt(arg) - conf.notes = NotesVerbosity[gVerbosity] + conf.verbosity = parseInt(arg) + conf.notes = NotesVerbosity[conf.verbosity] incl(conf.notes, conf.enableNotes) excl(conf.notes, conf.disableNotes) conf.mainPackageNotes = conf.notes of "parallelbuild": expectArg(conf, switch, arg, pass, info) - gNumberOfProcessors = parseInt(arg) + conf.numberOfProcessors = parseInt(arg) of "version", "v": expectNoArg(conf, switch, arg, pass, info) - writeVersionInfo(pass) + writeVersionInfo(conf, pass) of "advanced": expectNoArg(conf, switch, arg, pass, info) - writeAdvancedUsage(pass) + writeAdvancedUsage(conf, pass) of "fullhelp": expectNoArg(conf, switch, arg, pass, info) - writeFullhelp(pass) + writeFullhelp(conf, pass) of "help", "h": expectNoArg(conf, switch, arg, pass, info) - helpOnError(pass) + helpOnError(conf, pass) of "symbolfiles": case arg.normalize - of "on": gSymbolFiles = enabledSf - of "off": gSymbolFiles = disabledSf - of "writeonly": gSymbolFiles = writeOnlySf - of "readonly": gSymbolFiles = readOnlySf - of "v2": gSymbolFiles = v2Sf + of "on": conf.symbolFiles = enabledSf + of "off": conf.symbolFiles = disabledSf + of "writeonly": conf.symbolFiles = writeOnlySf + of "readonly": conf.symbolFiles = readOnlySf + of "v2": conf.symbolFiles = v2Sf else: localError(conf, info, "invalid option for --symbolFiles: " & arg) of "skipcfg": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optSkipConfigFile) + incl(conf.globalOptions, optSkipConfigFile) of "skipprojcfg": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optSkipProjConfigFile) + incl(conf.globalOptions, optSkipProjConfigFile) of "skipusercfg": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optSkipUserConfigFile) + incl(conf.globalOptions, optSkipUserConfigFile) of "skipparentcfg": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optSkipParentConfigFiles) + incl(conf.globalOptions, optSkipParentConfigFiles) of "genscript", "gendeps": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optGenScript) - incl(gGlobalOptions, optCompileOnly) + incl(conf.globalOptions, optGenScript) + incl(conf.globalOptions, optCompileOnly) of "colors": processOnOffSwitchG(conf, {optUseColors}, arg, pass, info) of "lib": expectArg(conf, switch, arg, pass, info) @@ -677,7 +677,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; conf.ideCmd = ideDef of "eval": expectArg(conf, switch, arg, pass, info) - gEvalExpr = arg + conf.evalExpr = arg of "context": expectNoArg(conf, switch, arg, pass, info) conf.ideCmd = ideCon @@ -686,15 +686,15 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; conf.ideCmd = ideUse of "stdout": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optStdout) + incl(conf.globalOptions, optStdout) of "listfullpaths": expectNoArg(conf, switch, arg, pass, info) - gListFullPaths = true + incl conf.globalOptions, optListFullPaths of "dynliboverride": dynlibOverride(conf, switch, arg, pass, info) of "dynliboverrideall": expectNoArg(conf, switch, arg, pass, info) - gDynlibOverrideAll = true + incl conf.globalOptions, optDynlibOverrideAll of "cs": # only supported for compatibility. Does nothing. expectArg(conf, switch, arg, pass, info) @@ -708,7 +708,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; localError(conf, info, "unknown experimental feature") of "nocppexceptions": expectNoArg(conf, switch, arg, pass, info) - incl(gGlobalOptions, optNoCppExceptions) + incl(conf.globalOptions, optNoCppExceptions) defineSymbol(conf.symbols, "noCppExceptions") of "cppdefine": expectArg(conf, switch, arg, pass, info) @@ -721,7 +721,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; defineSymbol(conf.symbols, "nimNewRuntime") of "cppcompiletonamespace": expectNoArg(conf, switch, arg, pass, info) - useNimNamespace = true + incl conf.globalOptions, optUseNimNamespace defineSymbol(conf.symbols, "cppCompileToNamespace") else: if strutils.find(switch, '.') >= 0: options.setConfigVar(conf, switch, arg) diff --git a/compiler/docgen.nim b/compiler/docgen.nim index 7fca27cc9..7ab2f0eee 100644 --- a/compiler/docgen.nim +++ b/compiler/docgen.nim @@ -29,7 +29,7 @@ type jArray: JsonNode types: TStrTable isPureRst: bool - conf: ConfigRef + conf*: ConfigRef PDoc* = ref TDocumentor ## Alias to type less. @@ -90,7 +90,7 @@ proc newDocumentor*(filename: string, conf: ConfigRef): PDoc = declareClosures() new(result) result.conf = conf - initRstGenerator(result[], (if gCmd != cmdRst2tex: outHtml else: outLatex), + initRstGenerator(result[], (if conf.cmd != cmdRst2tex: outHtml else: outLatex), conf.configVars, filename, {roSupportRawDirective}, docgenFindFile, compilerMsgHandler) @@ -117,8 +117,8 @@ proc newDocumentor*(filename: string, conf: ConfigRef): PDoc = result.onTestSnippet = proc (d: var RstGenerator; filename, cmd: string; status: int; content: string) = localError(conf, newLineInfo(conf, d.filename, -1, -1), warnUser, "only 'rst2html' supports the ':test:' attribute") -proc dispA(dest: var Rope, xml, tex: string, args: openArray[Rope]) = - if gCmd != cmdRst2tex: addf(dest, xml, args) +proc dispA(conf: ConfigRef; dest: var Rope, xml, tex: string, args: openArray[Rope]) = + if conf.cmd != cmdRst2tex: addf(dest, xml, args) else: addf(dest, tex, args) proc getVarIdx(varnames: openArray[string], id: string): int = @@ -231,37 +231,37 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe of tkEof: break of tkComment: - dispA(result, "$1", "\\spanComment{$1}", + dispA(d.conf, result, "$1", "\\spanComment{$1}", [rope(esc(d.target, literal))]) of tokKeywordLow..tokKeywordHigh: - dispA(result, "$1", "\\spanKeyword{$1}", + dispA(d.conf, result, "$1", "\\spanKeyword{$1}", [rope(literal)]) of tkOpr: - dispA(result, "$1", "\\spanOperator{$1}", + dispA(d.conf, result, "$1", "\\spanOperator{$1}", [rope(esc(d.target, literal))]) of tkStrLit..tkTripleStrLit: - dispA(result, "$1", + dispA(d.conf, result, "$1", "\\spanStringLit{$1}", [rope(esc(d.target, literal))]) of tkCharLit: - dispA(result, "$1", "\\spanCharLit{$1}", + dispA(d.conf, result, "$1", "\\spanCharLit{$1}", [rope(esc(d.target, literal))]) of tkIntLit..tkUInt64Lit: - dispA(result, "$1", + dispA(d.conf, result, "$1", "\\spanDecNumber{$1}", [rope(esc(d.target, literal))]) of tkFloatLit..tkFloat128Lit: - dispA(result, "$1", + dispA(d.conf, result, "$1", "\\spanFloatNumber{$1}", [rope(esc(d.target, literal))]) of tkSymbol: - dispA(result, "$1", + dispA(d.conf, result, "$1", "\\spanIdentifier{$1}", [rope(esc(d.target, literal))]) of tkSpaces, tkInvalid: add(result, literal) of tkCurlyDotLe: - dispA(result, """$1
""", + dispA(d.conf, result, """$1
""", "\\spanOther{$1}", [rope(esc(d.target, literal))]) of tkCurlyDotRi: - dispA(result, "
$1", + dispA(d.conf, result, "
$1", "\\spanOther{$1}", [rope(esc(d.target, literal))]) of tkParLe, tkParRi, tkBracketLe, tkBracketRi, tkCurlyLe, tkCurlyRi, @@ -270,7 +270,7 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe tkAccent, tkColonColon, tkGStrLit, tkGTripleStrLit, tkInfixOpr, tkPrefixOpr, tkPostfixOpr, tkBracketLeColon: - dispA(result, "$1", "\\spanOther{$1}", + dispA(d.conf, result, "$1", "\\spanOther{$1}", [rope(esc(d.target, literal))]) proc getAllRunnableExamples(d: PDoc; n: PNode; dest: var Rope) = @@ -278,7 +278,7 @@ proc getAllRunnableExamples(d: PDoc; n: PNode; dest: var Rope) = of nkCallKinds: if n[0].kind == nkSym and n[0].sym.magic == mRunnableExamples and n.len >= 2 and n.lastSon.kind == nkStmtList: - dispA(dest, "\n$1\n", + dispA(d.conf, dest, "\n$1\n", "\n\\textbf{$1}\n", [rope"Examples:"]) inc d.listingCounter let id = $d.listingCounter @@ -509,7 +509,7 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) = if gitUrl.len > 0: var commit = getConfigVar(d.conf, "git.commit") if commit.len == 0: commit = "master" - dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(d.conf, docItemSeeSrc, + dispA(d.conf, seeSrcRope, "$1", "", [ropeFormatNamedVars(d.conf, docItemSeeSrc, ["path", "line", "url", "commit"], [rope path, rope($n.info.line), rope gitUrl, rope commit])]) @@ -578,7 +578,7 @@ proc traceDeps(d: PDoc, it: PNode) = traceDeps(d, a) else: if d.section[k] != nil: add(d.section[k], ", ") - dispA(d.section[k], + dispA(d.conf, d.section[k], "$1", "$1", [rope(getModuleName(d.conf, it))]) @@ -750,7 +750,7 @@ proc genOutFile(d: PDoc): Rope = "tableofcontents", "moduledesc", "date", "time", "content"], [title.rope, toc, d.modDesc, rope(getDateStr()), rope(getClockStr()), code]) - if optCompileOnly notin gGlobalOptions: + if optCompileOnly notin d.conf.globalOptions: # XXX what is this hack doing here? 'optCompileOnly' means raw output!? code = ropeFormatNamedVars(d.conf, getConfigVar(d.conf, "doc.file"), ["title", "tableofcontents", "moduledesc", "date", "time", @@ -763,12 +763,12 @@ proc genOutFile(d: PDoc): Rope = result = code proc generateIndex*(d: PDoc) = - if optGenIndex in gGlobalOptions: + if optGenIndex in d.conf.globalOptions: writeIndexFile(d[], splitFile(d.conf.outFile).dir / splitFile(d.filename).name & IndexExt) proc getOutFile2(conf: ConfigRef; filename, ext, dir: string): string = - if gWholeProject: + if optWholeProject in conf.globalOptions: let d = if conf.outFile != "": conf.outFile else: dir createDir(d) result = d / changeFileExt(filename, ext) @@ -777,7 +777,7 @@ proc getOutFile2(conf: ConfigRef; filename, ext, dir: string): string = proc writeOutput*(d: PDoc, filename, outExt: string, useWarning = false) = var content = genOutFile(d) - if optStdout in gGlobalOptions: + if optStdout in d.conf.globalOptions: writeRope(stdout, content) else: writeRope(content, getOutFile2(d.conf, filename, outExt, "htmldocs"), useWarning) @@ -787,7 +787,7 @@ proc writeOutputJson*(d: PDoc, filename, outExt: string, let content = %*{"orig": d.filename, "nimble": getPackageName(d.conf, d.filename), "entries": d.jArray} - if optStdout in gGlobalOptions: + if optStdout in d.conf.globalOptions: write(stdout, $content) else: var f: File @@ -857,7 +857,7 @@ proc commandJson*(conf: ConfigRef) = let json = d.jArray let content = rope(pretty(json)) - if optStdout in gGlobalOptions: + if optStdout in d.conf.globalOptions: writeRope(stdout, content) else: #echo getOutFile(gProjectFull, JsonExt) @@ -872,7 +872,7 @@ proc commandTags*(conf: ConfigRef) = content: Rope generateTags(d, ast, content) - if optStdout in gGlobalOptions: + if optStdout in d.conf.globalOptions: writeRope(stdout, content) else: #echo getOutFile(gProjectFull, TagsExt) diff --git a/compiler/docgen2.nim b/compiler/docgen2.nim index c975e6cc7..d9a73e1cd 100644 --- a/compiler/docgen2.nim +++ b/compiler/docgen2.nim @@ -25,8 +25,8 @@ template closeImpl(body: untyped) {.dirty.} = var g = PGen(p) let useWarning = sfMainModule notin g.module.flags #echo g.module.name.s, " ", g.module.owner.id, " ", gMainPackageId - if (g.module.owner.id == gMainPackageId and gWholeProject) or - sfMainModule in g.module.flags: + if (g.module.owner.id == gMainPackageId and optWholeProject in g.doc.conf.globalOptions) or + sfMainModule in g.module.flags: body try: generateIndex(g.doc) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 8f67a7fb6..3f0e6f611 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -390,7 +390,7 @@ proc getConfigVar(conf: ConfigRef; c: TSystemCC, suffix: string): string = suffix if (platform.hostOS != targetOS or platform.hostCPU != targetCPU) and - optCompileOnly notin gGlobalOptions: + optCompileOnly notin conf.globalOptions: let fullCCname = platform.CPU[targetCPU].name & '.' & platform.OS[targetOS].name & '.' & CC[c].name & fullSuffix @@ -496,7 +496,7 @@ proc noAbsolutePaths(conf: ConfigRef): bool {.inline.} = # really: Cross compilation from Linux to Linux for example is entirely # reasonable. # `optGenMapping` is included here for niminst. - result = gGlobalOptions * {optGenScript, optGenMapping} != {} + result = conf.globalOptions * {optGenScript, optGenMapping} != {} proc cFileSpecificOptions(conf: ConfigRef; cfilename: string): string = result = compileOptions @@ -505,15 +505,15 @@ proc cFileSpecificOptions(conf: ConfigRef; cfilename: string): string = addOpt(result, option) let trunk = splitFile(cfilename).name - if optCDebug in gGlobalOptions: + if optCDebug in conf.globalOptions: let key = trunk & ".debug" if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key)) else: addOpt(result, getDebug(conf, cCompiler)) - if optOptimizeSpeed in gOptions: + if optOptimizeSpeed in conf.options: let key = trunk & ".speed" if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key)) else: addOpt(result, getOptSpeed(conf, cCompiler)) - elif optOptimizeSize in gOptions: + elif optOptimizeSize in conf.options: let key = trunk & ".size" if existsConfigVar(conf, key): addOpt(result, getConfigVar(conf, key)) else: addOpt(result, getOptSize(conf, cCompiler)) @@ -531,7 +531,7 @@ proc getLinkOptions(conf: ConfigRef): string = result.add(join([CC[cCompiler].linkDirCmd, libDir.quoteShell])) proc needsExeExt(conf: ConfigRef): bool {.inline.} = - result = (optGenScript in gGlobalOptions and targetOS == osWindows) or + result = (optGenScript in conf.globalOptions and targetOS == osWindows) or (platform.hostOS == osWindows) proc getCompilerExe(conf: ConfigRef; compiler: TSystemCC; cfile: string): string = @@ -556,7 +556,7 @@ proc getCompileCFileCmd*(conf: ConfigRef; cfile: Cfile): string = if exe.len == 0: exe = getCompilerExe(conf, c, cfile.cname) if needsExeExt(conf): exe = addFileExt(exe, "exe") - if optGenDynLib in gGlobalOptions and + if optGenDynLib in conf.globalOptions and ospNeedsPIC in platform.OS[targetOS].props: add(options, ' ' & CC[c].pic) @@ -628,7 +628,7 @@ proc externalFileChanged(conf: ConfigRef; cfile: Cfile): bool = close(f) proc addExternalFileToCompile*(conf: ConfigRef; c: var Cfile) = - if optForceFullMake notin gGlobalOptions and not externalFileChanged(conf, c): + if optForceFullMake notin conf.globalOptions and not externalFileChanged(conf, c): c.flags.incl CfileFlag.Cached toCompile.add(c) @@ -644,16 +644,16 @@ proc compileCFile(conf: ConfigRef; list: CFileList, script: var Rope, cmds: var # call the C compiler for the .c file: if it.flags.contains(CfileFlag.Cached): continue var compileCmd = getCompileCFileCmd(conf, it) - if optCompileOnly notin gGlobalOptions: + if optCompileOnly notin conf.globalOptions: add(cmds, compileCmd) let (_, name, _) = splitFile(it.cname) add(prettyCmds, "CC: " & name) - if optGenScript in gGlobalOptions: + if optGenScript in conf.globalOptions: add(script, compileCmd) add(script, tnl) proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string = - if optGenStaticLib in gGlobalOptions: + if optGenStaticLib in conf.globalOptions: var libname: string if conf.outFile.len > 0: libname = conf.outFile.expandTilde @@ -670,10 +670,10 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string = if needsExeExt(conf): linkerExe = addFileExt(linkerExe, "exe") if noAbsolutePaths(conf): result = linkerExe else: result = joinPath(ccompilerpath, linkerExe) - let buildgui = if optGenGuiApp in gGlobalOptions: CC[cCompiler].buildGui + let buildgui = if optGenGuiApp in conf.globalOptions: CC[cCompiler].buildGui else: "" var exefile, builddll: string - if optGenDynLib in gGlobalOptions: + if optGenDynLib in conf.globalOptions: exefile = platform.OS[targetOS].dllFrmt % splitFile(projectfile).name builddll = CC[cCompiler].buildDll else: @@ -687,7 +687,7 @@ proc getLinkCmd(conf: ConfigRef; projectfile, objfiles: string): string = if not exefile.isAbsolute(): exefile = joinPath(splitFile(projectfile).dir, exefile) when false: - if optCDebug in gGlobalOptions: + if optCDebug in conf.globalOptions: writeDebugInfo(exefile.changeFileExt("ndb")) exefile = quoteShell(exefile) let linkOptions = getLinkOptions(conf) & " " & @@ -720,7 +720,7 @@ template tryExceptOSErrorMessage(conf: ConfigRef; errorPrefix: string = "", body proc execLinkCmd(conf: ConfigRef; linkCmd: string) = tryExceptOSErrorMessage(conf, "invocation of external linker program failed."): execExternalProgram(conf, linkCmd, - if optListCmd in gGlobalOptions or gVerbosity > 1: hintExecuting else: hintLinking) + if optListCmd in conf.globalOptions or conf.verbosity > 1: hintExecuting else: hintLinking) proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx: int)) = let runCb = proc (idx: int, p: Process) = @@ -729,9 +729,9 @@ proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx: rawMessage(conf, errGenerated, "execution of an external compiler program '" & cmds[idx] & "' failed with exit code: " & $exitCode & "\n\n" & p.outputStream.readAll.strip) - if gNumberOfProcessors == 0: gNumberOfProcessors = countProcessors() + if conf.numberOfProcessors == 0: conf.numberOfProcessors = countProcessors() var res = 0 - if gNumberOfProcessors <= 1: + if conf.numberOfProcessors <= 1: for i in countup(0, high(cmds)): tryExceptOSErrorMessage(conf, "invocation of external compiler program failed."): res = execWithEcho(conf, cmds[i]) @@ -740,24 +740,24 @@ proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx: cmds[i]) else: tryExceptOSErrorMessage(conf, "invocation of external compiler program failed."): - if optListCmd in gGlobalOptions or gVerbosity > 1: + if optListCmd in conf.globalOptions or conf.verbosity > 1: res = execProcesses(cmds, {poEchoCmd, poStdErrToStdOut, poUsePath}, - gNumberOfProcessors, afterRunEvent=runCb) - elif gVerbosity == 1: + conf.numberOfProcessors, afterRunEvent=runCb) + elif conf.verbosity == 1: res = execProcesses(cmds, {poStdErrToStdOut, poUsePath}, - gNumberOfProcessors, prettyCb, afterRunEvent=runCb) + conf.numberOfProcessors, prettyCb, afterRunEvent=runCb) else: res = execProcesses(cmds, {poStdErrToStdOut, poUsePath}, - gNumberOfProcessors, afterRunEvent=runCb) + conf.numberOfProcessors, afterRunEvent=runCb) if res != 0: - if gNumberOfProcessors <= 1: + if conf.numberOfProcessors <= 1: rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" % cmds.join()) proc callCCompiler*(conf: ConfigRef; projectfile: string) = var linkCmd: string - if gGlobalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}: + if conf.globalOptions * {optCompileOnly, optGenScript} == {optCompileOnly}: return # speed up that call if only compiling and no script shall be # generated #var c = cCompiler @@ -767,9 +767,9 @@ proc callCCompiler*(conf: ConfigRef; projectfile: string) = let prettyCb = proc (idx: int) = echo prettyCmds[idx] compileCFile(conf, toCompile, script, cmds, prettyCmds) - if optCompileOnly notin gGlobalOptions: + if optCompileOnly notin conf.globalOptions: execCmdsInParallel(conf, cmds, prettyCb) - if optNoLinking notin gGlobalOptions: + if optNoLinking notin conf.globalOptions: # call the linker: var objfiles = "" for it in externalToLink: @@ -783,11 +783,11 @@ proc callCCompiler*(conf: ConfigRef; projectfile: string) = add(objfiles, quoteShell(objFile)) linkCmd = getLinkCmd(conf, projectfile, objfiles) - if optCompileOnly notin gGlobalOptions: + if optCompileOnly notin conf.globalOptions: execLinkCmd(conf, linkCmd) else: linkCmd = "" - if optGenScript in gGlobalOptions: + if optGenScript in conf.globalOptions: add(script, linkCmd) add(script, tnl) generateScript(conf, projectfile, script) @@ -892,7 +892,7 @@ proc genMappingFiles(conf: ConfigRef; list: CFileList): Rope = addf(result, "--file:r\"$1\"$N", [rope(it.cname)]) proc writeMapping*(conf: ConfigRef; symbolMapping: Rope) = - if optGenMapping notin gGlobalOptions: return + if optGenMapping notin conf.globalOptions: return var code = rope("[C_Files]\n") add(code, genMappingFiles(conf, toCompile)) add(code, "\n[C_Compiler]\nFlags=") diff --git a/compiler/hlo.nim b/compiler/hlo.nim index 76404e49b..8251e3179 100644 --- a/compiler/hlo.nim +++ b/compiler/hlo.nim @@ -17,7 +17,7 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode = # aweful to semcheck before macro invocation, so we don't and treat # templates and macros as immediate in this context. var rule: string - if optHints in gOptions and hintPattern in c.config.notes: + if optHints in c.config.options and hintPattern in c.config.notes: rule = renderTree(n, {renderNoComments}) let s = n.sons[0].sym case s.kind @@ -27,7 +27,7 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode = result = semTemplateExpr(c, n, s, {efFromHlo}) else: result = semDirectOp(c, n, {}) - if optHints in gOptions and hintPattern in c.config.notes: + if optHints in c.config.options and hintPattern in c.config.notes: message(c.config, orig.info, hintPattern, rule & " --> '" & renderTree(result, {renderNoComments}) & "'") @@ -92,12 +92,12 @@ proc hlo(c: PContext, n: PNode): PNode = proc hloBody(c: PContext, n: PNode): PNode = # fast exit: - if c.patterns.len == 0 or optPatterns notin gOptions: return n + if c.patterns.len == 0 or optPatterns notin c.config.options: return n c.hloLoopDetector = 0 result = hlo(c, n) proc hloStmt(c: PContext, n: PNode): PNode = # fast exit: - if c.patterns.len == 0 or optPatterns notin gOptions: return n + if c.patterns.len == 0 or optPatterns notin c.config.options: return n c.hloLoopDetector = 0 result = hlo(c, n) diff --git a/compiler/importer.nim b/compiler/importer.nim index 4e3aa8d10..ed988cea7 100644 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -122,7 +122,8 @@ proc importModuleAs(c: PContext; n: PNode, realModule: PSym): PSym = localError(c.config, n.info, "module alias must be an identifier") elif n.sons[1].ident.id != realModule.name.id: # some misguided guy will write 'import abc.foo as foo' ... - result = createModuleAlias(realModule, n.sons[1].ident, realModule.info) + result = createModuleAlias(realModule, n.sons[1].ident, realModule.info, + c.config.options) proc myImportModule(c: PContext, n: PNode): PSym = var f = checkModuleName(c.config, n) diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 2ec5a068d..25b554f7b 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -245,7 +245,7 @@ proc mangleName(m: BModule, s: PSym): Rope = inc i result = rope(x) if s.name.s != "this" and s.kind != skField: - if optHotCodeReloading in gOptions: + if optHotCodeReloading in m.config.options: # When hot reloading is enabled, we must ensure that the names # of functions and types will be preserved across rebuilds: add(result, idOrSig(s, m.module.name.s, m.sigConflicts)) @@ -1425,7 +1425,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) = s: Rope varCode: string varName = mangleName(p.module, v) - useReloadingGuard = sfGlobal in v.flags and optHotCodeReloading in gOptions + useReloadingGuard = sfGlobal in v.flags and optHotCodeReloading in p.config.options if v.constraint.isNil: if useReloadingGuard: @@ -1970,7 +1970,7 @@ proc genProc(oldProc: PProc, prc: PSym): Rope = else: result = ~tnl - if optHotCodeReloading in gOptions: + if optHotCodeReloading in p.config.options: # Here, we introduce thunks that create the equivalent of a jump table # for all global functions, because references to them may be stored # in JavaScript variables. The added indirection ensures that such diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 2410f1d36..773e5e29c 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -137,7 +137,7 @@ proc createStateType(g: ModuleGraph; iter: PSym): PType = rawAddSon(result, intType) proc createStateField(g: ModuleGraph; iter: PSym): PSym = - result = newSym(skField, getIdent(":state"), iter, iter.info) + result = newSym(skField, getIdent(":state"), iter, iter.info, {}) result.typ = createStateType(g, iter) proc createEnvObj(g: ModuleGraph; owner: PSym; info: TLineInfo): PType = @@ -151,7 +151,7 @@ proc getIterResult(iter: PSym): PSym = result = iter.ast.sons[resultPos].sym else: # XXX a bit hacky: - result = newSym(skResult, getIdent":result", iter, iter.info) + result = newSym(skResult, getIdent":result", iter, iter.info, {}) result.typ = iter.typ.sons[0] incl(result.flags, sfUsed) iter.ast.add newSymNode(result) @@ -228,14 +228,14 @@ proc interestingIterVar(s: PSym): bool {.inline.} = template isIterator*(owner: PSym): bool = owner.kind == skIterator and owner.typ.callConv == ccClosure -proc liftingHarmful(owner: PSym): bool {.inline.} = +proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} = ## lambda lifting can be harmful for JS-like code generators. let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro - result = gCmd == cmdCompileToJS and not isCompileTime + result = conf.cmd == cmdCompileToJS and not isCompileTime proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode = # transforms (iter) to (let env = newClosure[iter](); (iter, env)) - if liftingHarmful(owner): return n + if liftingHarmful(g.config, owner): return n let iter = n.sym assert iter.isIterator @@ -811,14 +811,14 @@ proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNo fn.typ.callConv = oldCC proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PNode = - # XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs + # XXX conf.cmd == cmdCompileToJS does not suffice! The compiletime stuff needs # the transformation even when compiling to JS ... # However we can do lifting for the stuff which is *only* compiletime. let isCompileTime = sfCompileTime in fn.flags or fn.kind == skMacro if body.kind == nkEmpty or ( - gCmd == cmdCompileToJS and not isCompileTime) or + g.config.cmd == cmdCompileToJS and not isCompileTime) or fn.skipGenericOwner.kind != skModule: # ignore forward declaration: result = body @@ -842,11 +842,8 @@ proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PN # echo renderTree(result, {renderIds}) proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode = - if body.kind == nkEmpty or gCmd == cmdCompileToJS: - result = body - else: - # XXX implement it properly - result = body + # XXX implement it properly + result = body # ------------------- iterator transformation -------------------------------- @@ -878,7 +875,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode = nkBreakState(cl.state) ... """ - if liftingHarmful(owner): return body + if liftingHarmful(g.config, owner): return body var L = body.len if not (body.kind == nkForStmt and body[L-2].kind in nkCallKinds): localError(g.config, body.info, "ignored invalid for loop") diff --git a/compiler/lexer.nim b/compiler/lexer.nim index d01b8c4be..591561987 100644 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -190,8 +190,8 @@ proc prettyTok*(tok: TToken): string = if isKeyword(tok.tokType): result = "keyword " & tok.ident.s else: result = tokToStr(tok) -proc printTok*(tok: TToken) = - msgWriteln($tok.line & ":" & $tok.col & "\t" & +proc printTok*(conf: ConfigRef; tok: TToken) = + msgWriteln(conf, $tok.line & ":" & $tok.col & "\t" & TokTypeToStr[tok.tokType] & " " & tokToStr(tok)) proc initToken*(L: var TToken) = @@ -714,7 +714,7 @@ proc handleCRLF(L: var TLexer, pos: int): int = if col > MaxLineLength: lexMessagePos(L, hintLineTooLong, pos) - if optEmbedOrigSrc in gGlobalOptions: + if optEmbedOrigSrc in L.config.globalOptions: let lineStart = cast[ByteAddress](L.buf) + L.lineStart let line = newString(cast[cstring](lineStart), col) addSourceLine(L.fileIdx, line) diff --git a/compiler/lookups.nim b/compiler/lookups.nim index e161d2e11..b6d63d0bd 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -85,7 +85,7 @@ proc skipAlias*(s: PSym; n: PNode; conf: ConfigRef): PSym = result = s else: result = s.owner - if gCmd == cmdPretty: + if conf.cmd == cmdPretty: prettybase.replaceDeprecated(n.info, s, result) else: message(conf, n.info, warnDeprecated, "use " & result.name.s & " instead; " & @@ -128,11 +128,11 @@ proc errorSym*(c: PContext, n: PNode): PSym = considerQuotedIdent(c.config, m) else: getIdent("err:" & renderTree(m)) - result = newSym(skError, ident, getCurrOwner(c), n.info) + result = newSym(skError, ident, getCurrOwner(c), n.info, {}) result.typ = errorType(c) incl(result.flags, sfDiscardable) # pretend it's imported from some unknown module to prevent cascading errors: - if gCmd != cmdInteractive and c.compilesContextId == 0: + if c.config.cmd != cmdInteractive and c.compilesContextId == 0: c.importTable.addSym(result) type @@ -176,7 +176,7 @@ proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope) = s = nextIter(it, scope.symbols) proc wrongRedefinition*(c: PContext; info: TLineInfo, s: string) = - if gCmd != cmdInteractive: + if c.config.cmd != cmdInteractive: localError(c.config, info, "redefinition of '$1'" % s) proc addDecl*(c: PContext, sym: PSym, info: TLineInfo) = diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 5b85ab008..13336f00e 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -49,7 +49,7 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode = let value = n.lastSon result = newNodeI(nkStmtList, n.info) - var temp = newSym(skTemp, getIdent(genPrefix), owner, value.info) + var temp = newSym(skTemp, getIdent(genPrefix), owner, value.info, g.config.options) temp.typ = skipTypes(value.typ, abstractInst) incl(temp.flags, sfFromGeneric) @@ -77,7 +77,7 @@ proc lowerTupleUnpackingForAsgn*(n: PNode; owner: PSym): PNode = let value = n.lastSon result = newNodeI(nkStmtList, n.info) - var temp = newSym(skLet, getIdent("_"), owner, value.info) + var temp = newSym(skLet, getIdent("_"), owner, value.info, owner.options) var v = newNodeI(nkLetSection, value.info) let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info) @@ -95,7 +95,7 @@ proc lowerTupleUnpackingForAsgn*(n: PNode; owner: PSym): PNode = proc lowerSwap*(n: PNode; owner: PSym): PNode = result = newNodeI(nkStmtList, n.info) # note: cannot use 'skTemp' here cause we really need the copy for the VM :-( - var temp = newSym(skVar, getIdent(genPrefix), owner, n.info) + var temp = newSym(skVar, getIdent(genPrefix), owner, n.info, owner.options) temp.typ = n.sons[1].typ incl(temp.flags, sfFromGeneric) @@ -121,7 +121,7 @@ proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType rawAddSon(result, getCompilerProc(g, "RootObj").typ) result.n = newNodeI(nkRecList, info) let s = newSym(skType, getIdent("Env_" & info.toFilename), - owner, info) + owner, info, owner.options) incl s.flags, sfAnon s.typ = result result.sym = s @@ -174,7 +174,8 @@ proc lookupInRecord(n: PNode, id: int): PSym = proc addField*(obj: PType; s: PSym) = # because of 'gensym' support, we have to mangle the name with its ID. # This is hacky but the clean solution is much more complex than it looks. - var field = newSym(skField, getIdent(s.name.s & $obj.n.len), s.owner, s.info) + var field = newSym(skField, getIdent(s.name.s & $obj.n.len), s.owner, s.info, + s.options) field.id = -s.id let t = skipIntLit(s.typ) field.typ = t @@ -185,7 +186,8 @@ proc addField*(obj: PType; s: PSym) = proc addUniqueField*(obj: PType; s: PSym): PSym {.discardable.} = result = lookupInRecord(obj.n, s.id) if result == nil: - var field = newSym(skField, getIdent(s.name.s & $obj.n.len), s.owner, s.info) + var field = newSym(skField, getIdent(s.name.s & $obj.n.len), s.owner, s.info, + s.options) field.id = -s.id let t = skipIntLit(s.typ) field.typ = t @@ -335,7 +337,8 @@ proc typeNeedsNoDeepCopy(t: PType): bool = proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; owner: PSym; typ: PType; v: PNode; useShallowCopy=false): PSym = - result = newSym(skTemp, getIdent(genPrefix), owner, varSection.info) + result = newSym(skTemp, getIdent(genPrefix), owner, varSection.info, + owner.options) result.typ = typ incl(result.flags, sfFromGeneric) @@ -449,7 +452,8 @@ proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym; t.n.add argsParam.newSymNode let name = (if f.kind == nkSym: f.sym.name.s else: genPrefix) & "Wrapper" - result = newSym(skProc, getIdent(name), argsParam.owner, f.info) + result = newSym(skProc, getIdent(name), argsParam.owner, f.info, + argsParam.options) result.ast = newProcNode(nkProcDef, f.info, body, params, newSymNode(result)) result.typ = t @@ -475,7 +479,7 @@ proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType; scratchOb # localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure") let fieldname = if i < formals.len: formals[i].sym.name else: tmpName - var field = newSym(skField, fieldname, objType.owner, n.info) + var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options) field.typ = argType objType.addField(field) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[i]) @@ -529,7 +533,7 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; scratchOb # localError(n.info, "'spawn'ed function cannot refer to 'ref'/closure") let fieldname = if i < formals.len: formals[i].sym.name else: tmpName - var field = newSym(skField, fieldname, objType.owner, n.info) + var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options) if argType.kind in {tyVarargs, tyOpenArray}: # important special case: we always create a zero-copy slice: @@ -537,7 +541,7 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; scratchOb slice.typ = n.typ slice.sons[0] = newSymNode(createMagic(g, "slice", mSlice)) slice.sons[0].typ = getSysType(g, n.info, tyInt) # fake type - var fieldB = newSym(skField, tmpName, objType.owner, n.info) + var fieldB = newSym(skField, tmpName, objType.owner, n.info, g.config.options) fieldB.typ = getSysType(g, n.info, tyInt) objType.addField(fieldB) @@ -547,7 +551,7 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; scratchOb objType.addField(field) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a) - var fieldA = newSym(skField, tmpName, objType.owner, n.info) + var fieldA = newSym(skField, tmpName, objType.owner, n.info, g.config.options) fieldA.typ = getSysType(g, n.info, tyInt) objType.addField(fieldA) result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldA), n[2]) @@ -615,12 +619,12 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P if n.kind notin nkCallKinds: localError(g.config, n.info, "'spawn' takes a call expression") return - if optThreadAnalysis in gGlobalOptions: + if optThreadAnalysis in g.config.globalOptions: if {tfThread, tfNoSideEffect} * n[0].typ.flags == {}: localError(g.config, n.info, "'spawn' takes a GC safe call expression") var - threadParam = newSym(skParam, getIdent"thread", owner, n.info) - argsParam = newSym(skParam, getIdent"args", owner, n.info) + threadParam = newSym(skParam, getIdent"thread", owner, n.info, g.config.options) + argsParam = newSym(skParam, getIdent"args", owner, n.info, g.config.options) block: let ptrType = getSysType(g, n.info, tyPointer) threadParam.typ = ptrType @@ -631,7 +635,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P incl(objType.flags, tfFinal) let castExpr = createCastExpr(argsParam, objType) - var scratchObj = newSym(skVar, getIdent"scratch", owner, n.info) + var scratchObj = newSym(skVar, getIdent"scratch", owner, n.info, g.config.options) block: scratchObj.typ = objType incl(scratchObj.flags, sfFromGeneric) @@ -649,7 +653,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P skFunc, skMethod, skConverter}): # for indirect calls we pass the function pointer in the scratchObj var argType = n[0].typ.skipTypes(abstractInst) - var field = newSym(skField, getIdent"fn", owner, n.info) + var field = newSym(skField, getIdent"fn", owner, n.info, g.config.options) field.typ = argType objType.addField(field) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[0]) @@ -673,7 +677,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P if barrier != nil: let typ = newType(tyPtr, owner) typ.rawAddSon(magicsys.getCompilerProc(g, "Barrier").typ) - var field = newSym(skField, getIdent"barrier", owner, n.info) + var field = newSym(skField, getIdent"barrier", owner, n.info, g.config.options) field.typ = typ objType.addField(field) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), barrier) @@ -681,7 +685,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P var fvField, fvAsExpr: PNode = nil if spawnKind == srFlowVar: - var field = newSym(skField, getIdent"fv", owner, n.info) + var field = newSym(skField, getIdent"fv", owner, n.info, g.config.options) field.typ = retType objType.addField(field) fvField = newDotExpr(scratchObj, field) @@ -692,7 +696,7 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField) elif spawnKind == srByVar: - var field = newSym(skField, getIdent"fv", owner, n.info) + var field = newSym(skField, getIdent"fv", owner, n.info, g.config.options) field.typ = newType(tyPtr, objType.owner) field.typ.rawAddSon(retType) objType.addField(field) diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim index aabcfd7a6..b5577d961 100644 --- a/compiler/magicsys.nim +++ b/compiler/magicsys.nim @@ -29,7 +29,7 @@ proc getSysSym*(g: ModuleGraph; info: TLineInfo; name: string): PSym = result = strTableGet(g.systemModule.tab, getIdent(name)) if result == nil: localError(g.config, info, "system module needs: " & name) - result = newSym(skError, getIdent(name), g.systemModule, g.systemModule.info) + result = newSym(skError, getIdent(name), g.systemModule, g.systemModule.info, {}) result.typ = newType(tyError, g.systemModule) if result.kind == skStub: loadStub(result) if result.kind == skAlias: result = result.owner @@ -57,7 +57,7 @@ proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSy r = nextIdentIter(ti, g.systemModule.tab) if result != nil: return result localError(g.config, info, "system module needs: " & name) - result = newSym(skError, id, g.systemModule, g.systemModule.info) + result = newSym(skError, id, g.systemModule, g.systemModule.info, {}) result.typ = newType(tyError, g.systemModule) proc sysTypeFromName*(g: ModuleGraph; info: TLineInfo; name: string): PType = diff --git a/compiler/main.nim b/compiler/main.nim index b9afc6a8d..69b33653b 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -20,8 +20,8 @@ import from magicsys import resetSysTypes -proc rodPass = - if gSymbolFiles in {enabledSf, writeOnlySf}: +proc rodPass(g: ModuleGraph) = + if g.config.symbolFiles in {enabledSf, writeOnlySf}: registerPass(rodwritePass) proc codegenPass = @@ -56,7 +56,7 @@ proc commandCheck(graph: ModuleGraph; cache: IdentCache) = graph.config.errorMax = high(int) # do not stop after first error defineSymbol(graph.config.symbols, "nimcheck") semanticPasses() # use an empty backend for semantic checking only - rodPass() + rodPass(graph) compileProject(graph, cache) proc commandDoc2(graph: ModuleGraph; cache: IdentCache; json: bool) = @@ -73,16 +73,16 @@ proc commandCompileToC(graph: ModuleGraph; cache: IdentCache) = extccomp.initVars(conf) semanticPasses() registerPass(cgenPass) - rodPass() + rodPass(graph) #registerPass(cleanupPass()) compileProject(graph, cache) cgenWriteModules(graph.backend, conf) - if gCmd != cmdRun: + if conf.cmd != cmdRun: let proj = changeFileExt(conf.projectFull, "") extccomp.callCCompiler(conf, proj) extccomp.writeJsonBuildInstructions(conf, proj) - if optGenScript in gGlobalOptions: + if optGenScript in graph.config.globalOptions: writeDepsFile(graph, toGeneratedFile(conf, proj, "")) proc commandJsonScript(graph: ModuleGraph; cache: IdentCache) = @@ -144,7 +144,7 @@ proc commandScan(cache: IdentCache, config: ConfigRef) = openLexer(L, f, stream, cache, config) while true: rawGetTok(L, tok) - printTok(tok) + printTok(config, tok) if tok.tokType == tkEof: break closeLexer(L) else: @@ -159,78 +159,78 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) = setupModuleCache() # In "nim serve" scenario, each command must reset the registered passes clearPasses() - gLastCmdTime = epochTime() + conf.lastCmdTime = epochTime() conf.searchPaths.add(conf.libpath) setId(100) case conf.command.normalize of "c", "cc", "compile", "compiletoc": # compile means compileToC currently - gCmd = cmdCompileToC + conf.cmd = cmdCompileToC commandCompileToC(graph, cache) of "cpp", "compiletocpp": - gCmd = cmdCompileToCpp + conf.cmd = cmdCompileToCpp defineSymbol(graph.config.symbols, "cpp") commandCompileToC(graph, cache) of "objc", "compiletooc": - gCmd = cmdCompileToOC + conf.cmd = cmdCompileToOC defineSymbol(graph.config.symbols, "objc") commandCompileToC(graph, cache) of "run": - gCmd = cmdRun + conf.cmd = cmdRun when hasTinyCBackend: extccomp.setCC("tcc") commandCompileToC(graph, cache) else: rawMessage(conf, errGenerated, "'run' command not available; rebuild with -d:tinyc") of "js", "compiletojs": - gCmd = cmdCompileToJS + conf.cmd = cmdCompileToJS commandCompileToJS(graph, cache) of "doc0": wantMainModule(conf) - gCmd = cmdDoc + conf.cmd = cmdDoc loadConfigs(DocConfig, cache) commandDoc(conf) of "doc2", "doc": - gCmd = cmdDoc + conf.cmd = cmdDoc loadConfigs(DocConfig, cache) defineSymbol(conf.symbols, "nimdoc") commandDoc2(graph, cache, false) of "rst2html": - gCmd = cmdRst2html + conf.cmd = cmdRst2html loadConfigs(DocConfig, cache) commandRst2Html(conf) of "rst2tex": - gCmd = cmdRst2tex + conf.cmd = cmdRst2tex loadConfigs(DocTexConfig, cache) commandRst2TeX(conf) of "jsondoc0": wantMainModule(conf) - gCmd = cmdDoc + conf.cmd = cmdDoc loadConfigs(DocConfig, cache) wantMainModule(conf) defineSymbol(conf.symbols, "nimdoc") commandJson(conf) of "jsondoc2", "jsondoc": - gCmd = cmdDoc + conf.cmd = cmdDoc loadConfigs(DocConfig, cache) wantMainModule(conf) defineSymbol(conf.symbols, "nimdoc") commandDoc2(graph, cache, true) of "ctags": wantMainModule(conf) - gCmd = cmdDoc + conf.cmd = cmdDoc loadConfigs(DocConfig, cache) defineSymbol(conf.symbols, "nimdoc") commandTags(conf) of "buildindex": - gCmd = cmdDoc + conf.cmd = cmdDoc loadConfigs(DocConfig, cache) commandBuildIndex(conf) of "gendepend": - gCmd = cmdGenDepend + conf.cmd = cmdGenDepend commandGenDepend(graph, cache) of "dump": - gCmd = cmdDump + conf.cmd = cmdDump if getConfigVar(conf, "dump.format") == "json": wantMainModule(conf) @@ -247,48 +247,48 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) = (key: "lib_paths", val: libpaths) ] - msgWriteln($dumpdata, {msgStdout, msgSkipHook}) + msgWriteln(conf, $dumpdata, {msgStdout, msgSkipHook}) else: - msgWriteln("-- list of currently defined symbols --", + msgWriteln(conf, "-- list of currently defined symbols --", {msgStdout, msgSkipHook}) - for s in definedSymbolNames(conf.symbols): msgWriteln(s, {msgStdout, msgSkipHook}) - msgWriteln("-- end of list --", {msgStdout, msgSkipHook}) + for s in definedSymbolNames(conf.symbols): msgWriteln(conf, s, {msgStdout, msgSkipHook}) + msgWriteln(conf, "-- end of list --", {msgStdout, msgSkipHook}) - for it in conf.searchPaths: msgWriteln(it) + for it in conf.searchPaths: msgWriteln(conf, it) of "check": - gCmd = cmdCheck + conf.cmd = cmdCheck commandCheck(graph, cache) of "parse": - gCmd = cmdParse + conf.cmd = cmdParse wantMainModule(conf) discard parseFile(FileIndex conf.projectMainIdx, cache, conf) of "scan": - gCmd = cmdScan + conf.cmd = cmdScan wantMainModule(conf) commandScan(cache, conf) - msgWriteln("Beware: Indentation tokens depend on the parser's state!") + msgWriteln(conf, "Beware: Indentation tokens depend on the parser's state!") of "secret": - gCmd = cmdInteractive + conf.cmd = cmdInteractive commandInteractive(graph, cache) of "e": commandEval(graph, cache, mainCommandArg(conf)) of "nop", "help": # prevent the "success" message: - gCmd = cmdDump + conf.cmd = cmdDump of "jsonscript": - gCmd = cmdJsonScript + conf.cmd = cmdJsonScript commandJsonScript(graph, cache) else: rawMessage(conf, errGenerated, "invalid command: " & conf.command) if conf.errorCounter == 0 and - gCmd notin {cmdInterpret, cmdRun, cmdDump}: + conf.cmd notin {cmdInterpret, cmdRun, cmdDump}: when declared(system.getMaxMem): let usedMem = formatSize(getMaxMem()) & " peakmem" else: let usedMem = formatSize(getTotalMem()) rawMessage(conf, hintSuccessX, [$conf.linesCompiled, - formatFloat(epochTime() - gLastCmdTime, ffDecimal, 3), + formatFloat(epochTime() - conf.lastCmdTime, ffDecimal, 3), usedMem, if isDefined(conf, "release"): "Release Build" else: "Debug Build"]) diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index da3965186..460d0b4a5 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -59,7 +59,7 @@ proc stopCompile*(g: ModuleGraph): bool {.inline.} = result = doStopCompile != nil and doStopCompile() proc createMagic*(g: ModuleGraph; name: string, m: TMagic): PSym = - result = newSym(skProc, getIdent(name), nil, unknownLineInfo()) + result = newSym(skProc, getIdent(name), nil, unknownLineInfo(), {}) result.magic = m proc newModuleGraph*(config: ConfigRef = nil): ModuleGraph = diff --git a/compiler/modules.nim b/compiler/modules.nim index 3da1bbbc7..7bc32d42c 100644 --- a/compiler/modules.nim +++ b/compiler/modules.nim @@ -66,7 +66,7 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; cache: IdentCache, f gMainPackageId = result.owner.id when false: - if gCmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}: + if conf.cmd in {cmdCompileToC, cmdCompileToCpp, cmdCheck, cmdIdeTools}: rd = handleSymbolFile(result, cache) if result.id < 0: internalError("handleSymbolFile should have set the module's ID") diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 6586c9992..774a8b83c 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -313,7 +313,7 @@ proc msgWriteln*(conf: ConfigRef; s: string, flags: MsgFlags = {}) = ## This is used for 'nim dump' etc. where we don't have nimsuggest ## support. - #if gCmd == cmdIdeTools and optCDebug notin gGlobalOptions: return + #if conf.cmd == cmdIdeTools and optCDebug notin gGlobalOptions: return if not isNil(writelnHook) and msgSkipHook notin flags: writelnHook(s) diff --git a/compiler/nim.nim b/compiler/nim.nim index d8402a2af..d3e00017f 100644 --- a/compiler/nim.nim +++ b/compiler/nim.nim @@ -40,7 +40,7 @@ proc prependCurDir(f: string): string = proc handleCmdLine(cache: IdentCache; conf: ConfigRef) = condsyms.initDefines(conf.symbols) if paramCount() == 0: - writeCommandLineUsage(conf.helpWritten) + writeCommandLineUsage(conf, conf.helpWritten) else: # Process command line arguments: processCmdLine(passCmd1, "", conf) @@ -76,14 +76,14 @@ proc handleCmdLine(cache: IdentCache; conf: ConfigRef) = if conf.command == "": rawMessage(conf, errGenerated, "command missing") mainCommand(newModuleGraph(conf), cache) - if optHints in gOptions and hintGCStats in conf.notes: echo(GC_getStatistics()) + if optHints in conf.options and hintGCStats in conf.notes: echo(GC_getStatistics()) #echo(GC_getStatistics()) if conf.errorCounter == 0: when hasTinyCBackend: - if gCmd == cmdRun: + if conf.cmd == cmdRun: tccgen.run(conf.arguments) - if optRun in gGlobalOptions: - if gCmd == cmdCompileToJS: + if optRun in conf.globalOptions: + if conf.cmd == cmdCompileToJS: var ex: string if conf.outFile.len > 0: ex = conf.outFile.prependCurDir.quoteShell diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim index 6a26f8dc7..379d15ad6 100644 --- a/compiler/nimconf.nim +++ b/compiler/nimconf.nim @@ -123,7 +123,7 @@ proc parseDirective(L: var TLexer, tok: var TToken; config: ConfigRef; condStack of wEnd: doEnd(L, tok, condStack) of wWrite: ppGetTok(L, tok) - msgs.msgWriteln(strtabs.`%`(tokToStr(tok), config.configVars, + msgs.msgWriteln(config, strtabs.`%`(tokToStr(tok), config.configVars, {useEnvironment, useKey})) ppGetTok(L, tok) else: @@ -230,30 +230,30 @@ proc getSystemConfigPath(conf: ConfigRef; filename: string): string = if not existsFile(result): result = joinPath([p, "etc", filename]) if not existsFile(result): result = "/etc/" & filename -proc loadConfigs*(cfg: string; cache: IdentCache; config: ConfigRef = nil) = - setDefaultLibpath(config) +proc loadConfigs*(cfg: string; cache: IdentCache; conf: ConfigRef = nil) = + setDefaultLibpath(conf) - if optSkipConfigFile notin gGlobalOptions: - readConfigFile(getSystemConfigPath(config, cfg), cache, config) + if optSkipConfigFile notin conf.globalOptions: + readConfigFile(getSystemConfigPath(conf, cfg), cache, conf) - if optSkipUserConfigFile notin gGlobalOptions: - readConfigFile(getUserConfigPath(cfg), cache, config) + if optSkipUserConfigFile notin conf.globalOptions: + readConfigFile(getUserConfigPath(cfg), cache, conf) - let pd = if config.projectPath.len > 0: config.projectPath else: getCurrentDir() - if optSkipParentConfigFiles notin gGlobalOptions: + let pd = if conf.projectPath.len > 0: conf.projectPath else: getCurrentDir() + if optSkipParentConfigFiles notin conf.globalOptions: for dir in parentDirs(pd, fromRoot=true, inclusive=false): - readConfigFile(dir / cfg, cache, config) + readConfigFile(dir / cfg, cache, conf) - if optSkipProjConfigFile notin gGlobalOptions: - readConfigFile(pd / cfg, cache, config) + if optSkipProjConfigFile notin conf.globalOptions: + readConfigFile(pd / cfg, cache, conf) - if config.projectName.len != 0: + if conf.projectName.len != 0: # new project wide config file: - var projectConfig = changeFileExt(config.projectFull, "nimcfg") + var projectConfig = changeFileExt(conf.projectFull, "nimcfg") if not fileExists(projectConfig): - projectConfig = changeFileExt(config.projectFull, "nim.cfg") - readConfigFile(projectConfig, cache, config) + projectConfig = changeFileExt(conf.projectFull, "nim.cfg") + readConfigFile(projectConfig, cache, conf) -proc loadConfigs*(cfg: string; config: ConfigRef) = +proc loadConfigs*(cfg: string; conf: ConfigRef) = # for backwards compatibility only. - loadConfigs(cfg, newIdentCache(), config) + loadConfigs(cfg, newIdentCache(), conf) diff --git a/compiler/nimfix/nimfix.nim b/compiler/nimfix/nimfix.nim index 2ef375b00..c3e29f9a1 100644 --- a/compiler/nimfix/nimfix.nim +++ b/compiler/nimfix/nimfix.nim @@ -38,7 +38,7 @@ In addition, all command line options of Nim are supported. proc mainCommand = registerPass verbosePass registerPass semPass - gCmd = cmdPretty + conf.cmd = cmdPretty searchPaths.add options.libpath if gProjectFull.len != 0: # current path is always looked first for modules diff --git a/compiler/options.nim b/compiler/options.nim index c918cac68..56c3dcf0b 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -70,7 +70,7 @@ type # please make sure we have under 32 options optIdeTerse # idetools: use terse descriptions optNoCppExceptions # use C exception handling even with CPP optExcessiveStackTrace # fully qualified module filenames - opWholeProject # for 'doc2': output any dependency + optWholeProject # for 'doc2': output any dependency optListFullPaths optNoNimblePath optDynlibOverrideAll diff --git a/compiler/passaux.nim b/compiler/passaux.nim index f0d6bd44a..568fb4c23 100644 --- a/compiler/passaux.nim +++ b/compiler/passaux.nim @@ -26,7 +26,7 @@ proc verboseOpen(graph: ModuleGraph; s: PSym; cache: IdentCache): PPassContext = proc verboseProcess(context: PPassContext, n: PNode): PNode = result = n let v = VerboseRef(context) - if gVerbosity == 3: + if v.config.verbosity == 3: # system.nim deactivates all hints, for verbosity:3 we want the processing # messages nonetheless, so we activate them again unconditionally: incl(v.config.notes, hintProcessing) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 31d3f75a3..1bb10b80e 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -116,7 +116,7 @@ proc setExternName(c: PContext; s: PSym, extname: string, info: TLineInfo) = s.loc.r = rope(extname % s.name.s) except ValueError: localError(c.config, info, "invalid extern name: '" & extname & "'. (Forgot to escape '$'?)") - if gCmd == cmdPretty and '$' notin extname: + if c.config.cmd == cmdPretty and '$' notin extname: # note that '{.importc.}' is transformed into '{.importc: "$1".}' s.loc.flags.incl(lfFullExternalName) @@ -140,7 +140,7 @@ proc processImportCpp(c: PContext; s: PSym, extname: string, info: TLineInfo) = incl(s.flags, sfImportc) incl(s.flags, sfInfixCall) excl(s.flags, sfForward) - if gCmd == cmdCompileToC: + if c.config.cmd == cmdCompileToC: let m = s.getModule() incl(m.flags, sfCompileToCpp) extccomp.gMixedMode = true @@ -218,8 +218,8 @@ proc isTurnedOn(c: PContext, n: PNode): bool = localError(c.config, n.info, "'on' or 'off' expected") proc onOff(c: PContext, n: PNode, op: TOptions) = - if isTurnedOn(c, n): gOptions = gOptions + op - else: gOptions = gOptions - op + if isTurnedOn(c, n): c.config.options = c.config.options + op + else: c.config.options = c.config.options - op proc pragmaNoForward(c: PContext, n: PNode; flag=sfNoForward) = if isTurnedOn(c, n): incl(c.module.flags, flag) @@ -343,14 +343,14 @@ proc processOption(c: PContext, n: PNode): bool = else: case n.sons[1].ident.s.normalize of "speed": - incl(gOptions, optOptimizeSpeed) - excl(gOptions, optOptimizeSize) + incl(c.config.options, optOptimizeSpeed) + excl(c.config.options, optOptimizeSize) of "size": - excl(gOptions, optOptimizeSpeed) - incl(gOptions, optOptimizeSize) + excl(c.config.options, optOptimizeSpeed) + incl(c.config.options, optOptimizeSize) of "none": - excl(gOptions, optOptimizeSpeed) - excl(gOptions, optOptimizeSize) + excl(c.config.options, optOptimizeSpeed) + excl(c.config.options, optOptimizeSize) else: localError(c.config, n.info, "'none', 'speed' or 'size' expected") of wImplicitStatic: onOff(c, n, {optImplicitStatic}) of wPatterns: onOff(c, n, {optPatterns}) @@ -361,7 +361,7 @@ proc processPush(c: PContext, n: PNode, start: int) = localError(c.config, n.info, "'push' cannot have arguments") var x = newOptionEntry(c.config) var y = c.optionStack[^1] - x.options = gOptions + x.options = c.config.options x.defaultCC = y.defaultCC x.dynlib = y.dynlib x.notes = c.config.notes @@ -378,7 +378,7 @@ proc processPop(c: PContext, n: PNode) = if c.optionStack.len <= 1: localError(c.config, n.info, "{.pop.} without a corresponding {.push.}") else: - gOptions = c.optionStack[^1].options + c.config.options = c.optionStack[^1].options c.config.notes = c.optionStack[^1].notes c.optionStack.setLen(c.optionStack.len - 1) @@ -557,7 +557,7 @@ proc processPragma(c: PContext, n: PNode, i: int) = elif it[0].kind != nkIdent: invalidPragma(c, n) elif it[1].kind != nkIdent: invalidPragma(c, n) - var userPragma = newSym(skTemplate, it[1].ident, nil, it.info) + var userPragma = newSym(skTemplate, it[1].ident, nil, it.info, c.config.options) userPragma.ast = newNode(nkPragma, n.info, n.sons[i+1..^1]) strTableAdd(c.userPragmas, userPragma) @@ -635,7 +635,7 @@ proc deprecatedStmt(c: PContext; outerPragma: PNode) = if dest == nil or dest.kind in routineKinds: localError(c.config, n.info, warnUser, "the .deprecated pragma is unreliable for routines") let src = considerQuotedIdent(c.config, n[0]) - let alias = newSym(skAlias, src, dest, n[0].info) + let alias = newSym(skAlias, src, dest, n[0].info, c.config.options) incl(alias.flags, sfExported) if sfCompilerProc in dest.flags: markCompilerProc(c, alias) addInterfaceDecl(c, alias) @@ -657,7 +657,8 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym = # We return a dummy symbol; later passes over the type will repair it. # Generic instantiation needs to know about this too. But we're lazy # and perform the lookup on demand instead. - result = newSym(skUnknown, considerQuotedIdent(c.config, n), nil, n.info) + result = newSym(skUnknown, considerQuotedIdent(c.config, n), nil, n.info, + c.config.options) else: result = qualifiedLookUp(c, n, {checkUndeclared}) diff --git a/compiler/renderer.nim b/compiler/renderer.nim index a47c77464..966bed769 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -1456,9 +1456,7 @@ proc renderModule*(n: PNode, infile, outfile: string, nkCommentStmt: putNL(g) else: discard gcoms(g) - if optStdout in gGlobalOptions: - write(stdout, g.buf) - elif open(f, outfile, fmWrite): + if open(f, outfile, fmWrite): write(f, g.buf) close(f) else: diff --git a/compiler/rodread.nim b/compiler/rodread.nim index f62c24dfd..52e7a924c 100644 --- a/compiler/rodread.nim +++ b/compiler/rodread.nim @@ -623,16 +623,16 @@ proc processRodFile(r: PRodReader, hash: SecureHash) = of "OPTIONS": inc(r.pos) # skip ':' r.options = cast[TOptions](int32(decodeVInt(r.s, r.pos))) - if options.gOptions != r.options: r.reason = rrOptions + if r.config.options != r.options: r.reason = rrOptions of "GOPTIONS": inc(r.pos) # skip ':' var dep = cast[TGlobalOptions](int32(decodeVInt(r.s, r.pos))) - if gGlobalOptions-harmlessOptions != dep-harmlessOptions: + if r.config.globalOptions-harmlessOptions != dep-harmlessOptions: r.reason = rrOptions of "CMD": inc(r.pos) # skip ':' var dep = cast[TCommands](int32(decodeVInt(r.s, r.pos))) - if cmdChangeTriggersRecompilation(dep, gCmd): r.reason = rrOptions + if cmdChangeTriggersRecompilation(dep, r.config.cmd): r.reason = rrOptions of "DEFINES": inc(r.pos) # skip ':' d = 0 @@ -907,7 +907,7 @@ proc checkDep(fileIdx: FileIndex; cache: IdentCache; conf: ConfigRef): TReasonFo # we cannot break here, because of side-effects of `checkDep` if result != rrNone: rawMessage(conf, hintProcessing, reasonToFrmt[result] % filename) - if result != rrNone or optForceFullMake in gGlobalOptions: + if result != rrNone or optForceFullMake in conf.globalOptions: # recompilation is necessary: if r != nil: memfiles.close(r.memfile) r = nil @@ -915,7 +915,7 @@ proc checkDep(fileIdx: FileIndex; cache: IdentCache; conf: ConfigRef): TReasonFo gMods[fileIdx.int32].reason = result # now we know better proc handleSymbolFile*(module: PSym; cache: IdentCache; conf: ConfigRef): PRodReader = - if gSymbolFiles in {disabledSf, writeOnlySf, v2Sf}: + if conf.symbolFiles in {disabledSf, writeOnlySf, v2Sf}: module.id = getID() return nil idgen.loadMaxIds(conf, conf.projectPath / conf.projectName) @@ -1035,9 +1035,8 @@ proc writeSym(f: File; s: PSym) = if s.magic != mNone: f.write('@') f.write($s.magic) - if s.options != gOptions: - f.write('!') - f.write($s.options) + f.write('!') + f.write($s.options) if s.position != 0: f.write('%') f.write($s.position) diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim index 7dc10bbf5..4686baf2b 100644 --- a/compiler/rodwrite.nim +++ b/compiler/rodwrite.nim @@ -71,7 +71,7 @@ proc newRodWriter(hash: SecureHash, module: PSym; cache: IdentCache; result.hash = hash result.module = module result.defines = getDefines(config) - result.options = options.gOptions + result.options = config.options result.files = @[] result.inclDeps = "" result.modDeps = "" @@ -509,12 +509,12 @@ proc writeRod(w: PRodWriter) = f.write(rodNL) var goptions = "GOPTIONS:" - encodeVInt(cast[int32](gGlobalOptions), goptions) + encodeVInt(cast[int32](w.config.globalOptions), goptions) f.write(goptions) f.write(rodNL) var cmd = "CMD:" - encodeVInt(cast[int32](gCmd), cmd) + encodeVInt(cast[int32](w.config.cmd), cmd) f.write(cmd) f.write(rodNL) diff --git a/compiler/sem.nim b/compiler/sem.nim index 8cb233a05..c5c3dd99b 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -64,7 +64,7 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode; # templates perform some quick check whether the cursor is actually in # the generic or template. when defined(nimsuggest): - if gCmd == cmdIdeTools and requiresCheck: + if c.config.cmd == cmdIdeTools and requiresCheck: #if optIdeDebug in gGlobalOptions: # echo "passing to safeSemExpr: ", renderTree(n) discard safeSemExpr(c, n) @@ -562,9 +562,9 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = if result.kind != nkEmpty: addSon(a, result) result = a result = hloStmt(c, result) - if gCmd == cmdInteractive and not isEmptyType(result.typ): + if c.config.cmd == cmdInteractive and not isEmptyType(result.typ): result = buildEchoStmt(c, result) - if gCmd == cmdIdeTools: + if c.config.cmd == cmdIdeTools: appendToModule(c.module, result) result = transformStmt(c.graph, c.module, result) @@ -595,7 +595,7 @@ proc myProcess(context: PPassContext, n: PNode): PNode = result = nil else: result = ast.emptyNode - #if gCmd == cmdIdeTools: findSuggest(c, n) + #if c.config.cmd == cmdIdeTools: findSuggest(c, n) rod.storeNode(c.module, result) proc testExamples(c: PContext) = @@ -612,7 +612,7 @@ proc testExamples(c: PContext) = proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode = var c = PContext(context) - if gCmd == cmdIdeTools and not c.suggestionsMade: + if c.config.cmd == cmdIdeTools and not c.suggestionsMade: suggestSentinel(c) closeScope(c) # close module's scope rawCloseScope(c) # imported symbols; don't check for unused ones! diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 6f7a48dae..ad5bdfd49 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -204,7 +204,7 @@ proc considerGenSyms*(c: PContext; n: PNode) = proc newOptionEntry*(conf: ConfigRef): POptionEntry = new(result) - result.options = gOptions + result.options = conf.options result.defaultCC = ccDefault result.dynlib = nil result.notes = conf.notes @@ -286,7 +286,8 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType = proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode = let typedesc = makeTypeDesc(c, typ) - let sym = newSym(skType, c.cache.idAnon, getCurrOwner(c), info).linkTo(typedesc) + let sym = newSym(skType, c.cache.idAnon, getCurrOwner(c), info, + c.config.options).linkTo(typedesc) return newSymNode(sym, info) proc makeTypeFromExpr*(c: PContext, n: PNode): PType = diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 5fe7a7a69..2a2a8b72a 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -481,7 +481,7 @@ proc isAssignable(c: PContext, n: PNode; isUnsafeAddr=false): TAssignableResult result = parampatterns.isAssignable(c.p.owner, n, isUnsafeAddr) proc newHiddenAddrTaken(c: PContext, n: PNode): PNode = - if n.kind == nkHiddenDeref and not (gCmd == cmdCompileToCpp or + if n.kind == nkHiddenDeref and not (c.config.cmd == cmdCompileToCpp or sfCompileToCpp in c.module.flags): checkSonsLen(n, 1, c.config) result = n.sons[0] @@ -601,7 +601,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode = if {sfNoSideEffect, sfCompileTime} * callee.flags != {} and {sfForward, sfImportc} * callee.flags == {} and n.typ != nil: if sfCompileTime notin callee.flags and - optImplicitStatic notin gOptions: return + optImplicitStatic notin c.config.options: return if callee.magic notin ctfeWhitelist: return if callee.kind notin {skProc, skFunc, skConverter} or callee.isGenericRoutine: @@ -1078,7 +1078,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = # here at all! #if isSymChoice(n.sons[1]): return when defined(nimsuggest): - if gCmd == cmdIdeTools: + if c.config.cmd == cmdIdeTools: suggestExpr(c, n) if exactEquals(gTrackPos, n[1].info): suggestExprNoCheck(c, n) @@ -1931,7 +1931,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = if callee.magic != mNone: result = magicsAfterOverloadResolution(c, result, flags) of mRunnableExamples: - if gCmd == cmdDoc and n.len >= 2 and n.lastSon.kind == nkStmtList: + if c.config.cmd == cmdDoc and n.len >= 2 and n.lastSon.kind == nkStmtList: if sfMainModule in c.module.flags: let inp = toFullPath(c.module.info) if c.runnableExamples == nil: @@ -2205,7 +2205,7 @@ proc shouldBeBracketExpr(n: PNode): bool = proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = result = n - if gCmd == cmdIdeTools: suggestExpr(c, n) + if c.config.cmd == cmdIdeTools: suggestExpr(c, n) if nfSem in n.flags: return case n.kind of nkIdent, nkAccQuoted: @@ -2290,7 +2290,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = let mode = if nfDotField in n.flags: {} else: {checkUndeclared} var s = qualifiedLookUp(c, n.sons[0], mode) if s != nil: - #if gCmd == cmdPretty and n.sons[0].kind == nkDotExpr: + #if c.config.cmd == cmdPretty and n.sons[0].kind == nkDotExpr: # pretty.checkUse(n.sons[0].sons[1].info, s) case s.kind of skMacro: diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 48a81d110..daf9ce983 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -403,11 +403,11 @@ proc magicCall(m: PSym, n: PNode; g: ModuleGraph): PNode = result = evalOp(s.magic, n, a, b, c, g) proc getAppType(n: PNode; g: ModuleGraph): PNode = - if gGlobalOptions.contains(optGenDynLib): + if g.config.globalOptions.contains(optGenDynLib): result = newStrNodeT("lib", n, g) - elif gGlobalOptions.contains(optGenStaticLib): + elif g.config.globalOptions.contains(optGenStaticLib): result = newStrNodeT("staticlib", n, g) - elif gGlobalOptions.contains(optGenGuiApp): + elif g.config.globalOptions.contains(optGenGuiApp): result = newStrNodeT("gui", n, g) else: result = newStrNodeT("console", n, g) @@ -479,7 +479,7 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode = result = newNodeIT(nkCharLit, x.info, n.typ) if idx >= 0 and idx < len(x.strVal): result.intVal = ord(x.strVal[int(idx)]) - elif idx == len(x.strVal) and optLaxStrings in gOptions: + elif idx == len(x.strVal) and optLaxStrings in g.config.options: discard else: localError(g.config, n.info, "index out of bounds: " & $n) diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index a620c544d..8f06e748e 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -169,7 +169,7 @@ proc semGenericStmt(c: PContext, n: PNode, when defined(nimsuggest): if withinTypeDesc in flags: inc c.inTypeContext - #if gCmd == cmdIdeTools: suggestStmt(c, n) + #if conf.cmd == cmdIdeTools: suggestStmt(c, n) semIdeForTemplateOrGenericCheck(n, ctx.cursorInBody) case n.kind diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 015e81b1f..543161524 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -146,7 +146,7 @@ proc guardDotAccess(a: PEffects; n: PNode) = proc makeVolatile(a: PEffects; s: PSym) {.inline.} = template compileToCpp(a): untyped = - gCmd == cmdCompileToCpp or sfCompileToCpp in getModule(a.owner).flags + a.config.cmd == cmdCompileToCpp or sfCompileToCpp in getModule(a.owner).flags if a.inTryStmt > 0 and not compileToCpp(a): incl(s.flags, sfVolatile) @@ -186,7 +186,7 @@ proc markGcUnsafe(a: PEffects; reason: PNode) = a.owner.gcUnsafetyReason = reason.sym else: a.owner.gcUnsafetyReason = newSym(skUnknown, getIdent(""), - a.owner, reason.info) + a.owner, reason.info, {}) when true: template markSideEffect(a: PEffects; reason: typed) = @@ -282,7 +282,7 @@ proc addEffect(a: PEffects, e: PNode, useLineInfo=true) = var aa = a.exc for i in a.bottom ..< aa.len: if sameType(a.graph.excType(aa[i]), a.graph.excType(e)): - if not useLineInfo or gCmd == cmdDoc: return + if not useLineInfo or a.config.cmd == cmdDoc: return elif aa[i].info == e.info: return throws(a.exc, e) @@ -290,7 +290,7 @@ proc addTag(a: PEffects, e: PNode, useLineInfo=true) = var aa = a.tags for i in 0 ..< aa.len: if sameType(aa[i].typ.skipTypes(skipPtrs), e.typ.skipTypes(skipPtrs)): - if not useLineInfo or gCmd == cmdDoc: return + if not useLineInfo or a.config.cmd == cmdDoc: return elif aa[i].info == e.info: return throws(a.tags, e) @@ -960,7 +960,7 @@ proc trackProc*(g: ModuleGraph; s: PSym, body: PNode) = effects.sons[tagEffects] = tagsSpec if sfThread in s.flags and t.gcUnsafe: - if optThreads in gGlobalOptions and optThreadAnalysis in gGlobalOptions: + if optThreads in g.config.globalOptions and optThreadAnalysis in g.config.globalOptions: #localError(s.info, "'$1' is not GC-safe" % s.name.s) listGcUnsafety(s, onlyWarning=false, g.config) else: diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 0a51ccee4..7282ea58c 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -139,7 +139,7 @@ proc discardCheck(c: PContext, result: PNode) = while n.kind in skipForDiscardable: n = n.lastSon n.typ = nil - elif result.typ.kind != tyError and gCmd != cmdInteractive: + elif result.typ.kind != tyError and c.config.cmd != cmdInteractive: var n = result while n.kind in skipForDiscardable: n = n.lastSon var s = "expression '" & $n & "' is of type '" & @@ -255,7 +255,7 @@ proc semTry(c: PContext, n: PNode): PNode = # returns true if exception type is imported type let typ = semTypeNode(c, typeNode, nil).toObject() var is_imported = false - if isImportedException(typ): + if isImportedException(typ, c.config): is_imported = true elif not isException(typ): localError(c.config, typeNode.info, errExprCannotBeRaised) @@ -398,7 +398,7 @@ proc semUsing(c: PContext; n: PNode): PNode = if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope % "using") for i in countup(0, sonsLen(n)-1): var a = n.sons[i] - if gCmd == cmdIdeTools: suggestStmt(c, a) + if c.config.cmd == cmdIdeTools: suggestStmt(c, a) if a.kind == nkCommentStmt: continue if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a, c.config) checkMinSonsLen(a, 3, c.config) @@ -471,7 +471,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = var hasCompileTime = false for i in countup(0, sonsLen(n)-1): var a = n.sons[i] - if gCmd == cmdIdeTools: suggestStmt(c, a) + if c.config.cmd == cmdIdeTools: suggestStmt(c, a) if a.kind == nkCommentStmt: continue if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a, c.config) checkMinSonsLen(a, 3, c.config) @@ -578,7 +578,7 @@ proc semConst(c: PContext, n: PNode): PNode = result = copyNode(n) for i in countup(0, sonsLen(n) - 1): var a = n.sons[i] - if gCmd == cmdIdeTools: suggestStmt(c, a) + if c.config.cmd == cmdIdeTools: suggestStmt(c, a) if a.kind == nkCommentStmt: continue if a.kind != nkConstDef: illFormedAst(a, c.config) checkSonsLen(a, 3, c.config) @@ -756,7 +756,7 @@ proc semRaise(c: PContext, n: PNode): PNode = if n[0].kind != nkEmpty: n[0] = semExprWithType(c, n[0]) let typ = n[0].typ - if not isImportedException(typ): + if not isImportedException(typ, c.config): if typ.kind != tyRef or typ.lastSon.kind != tyObject: localError(c.config, n.info, errExprCannotBeRaised) if not isException(typ.lastSon): @@ -785,7 +785,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) = for i in countup(0, sonsLen(n) - 1): var a = n.sons[i] when defined(nimsuggest): - if gCmd == cmdIdeTools: + if c.config.cmd == cmdIdeTools: inc c.inTypeContext suggestStmt(c, a) dec c.inTypeContext @@ -1236,7 +1236,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = s.typ = newProcType(c, n.info) if n.sons[pragmasPos].kind != nkEmpty: pragma(c, s, n.sons[pragmasPos], lambdaPragmas) - s.options = gOptions + s.options = c.config.options if n.sons[bodyPos].kind != nkEmpty: if sfImportc in s.flags: localError(c.config, n.sons[bodyPos].info, errImplOfXNotAllowed % s.name.s) @@ -1565,7 +1565,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, proto.ast = n # needed for code generation popOwner(c) pushOwner(c, s) - s.options = gOptions + s.options = c.config.options if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n) if s.name.s[0] in {'.', '('}: if s.name.s in [".", ".()", ".="] and {destructor, dotOperators} * c.features == {}: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index f44d93f20..52afce688 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -451,7 +451,7 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType = else: addSon(result.n, newSymNode(field)) addSonSkipIntLit(result, typ) - if gCmd == cmdPretty: styleCheckDef(a.sons[j].info, field) + if c.config.cmd == cmdPretty: styleCheckDef(a.sons[j].info, field) if result.n.len == 0: result.n = nil proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, @@ -491,7 +491,7 @@ proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, else: discard else: result = semIdentVis(c, kind, n, allowed) - if gCmd == cmdPretty: styleCheckDef(n.info, result) + if c.config.cmd == cmdPretty: styleCheckDef(n.info, result) proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) = let ex = t[branchIndex][currentEx].skipConv @@ -1062,7 +1062,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, addSon(result.n, newSymNode(arg)) rawAddSon(result, finalType) addParamOrResult(c, arg, kind) - if gCmd == cmdPretty: styleCheckDef(a.sons[j].info, arg) + if c.config.cmd == cmdPretty: styleCheckDef(a.sons[j].info, arg) var r: PType if n.sons[0].kind != nkEmpty: @@ -1354,7 +1354,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = nil inc c.inTypeContext - if gCmd == cmdIdeTools: suggestExpr(c, n) + if c.config.cmd == cmdIdeTools: suggestExpr(c, n) case n.kind of nkEmpty: discard of nkTypeOfExpr: diff --git a/compiler/service.nim b/compiler/service.nim index 9b45f7bd7..f1a988ae5 100644 --- a/compiler/service.nim +++ b/compiler/service.nim @@ -42,7 +42,7 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string; config: ConfigRef) = of cmdArgument: if processArgument(pass, p, argsCount, config): break if pass == passCmd2: - if optRun notin gGlobalOptions and config.arguments.len > 0 and config.command.normalize != "run": + if optRun notin config.globalOptions and config.arguments.len > 0 and config.command.normalize != "run": rawMessage(config, errGenerated, errArgsNeedRunOption) proc serve*(cache: IdentCache; action: proc (cache: IdentCache){.nimcall.}; config: ConfigRef) = diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 01413f678..74c944d51 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -612,7 +612,7 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation = if tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags: return isNone elif tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {} and - optThreadAnalysis in gGlobalOptions: + optThreadAnalysis in c.c.config.globalOptions: # noSideEffect implies ``tfThread``! return isNone elif f.flags * {tfIterator} != a.flags * {tfIterator}: @@ -686,7 +686,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType = if alreadyBound != nil: typ = alreadyBound template paramSym(kind): untyped = - newSym(kind, typeParamName, typeClass.sym, typeClass.sym.info) + newSym(kind, typeParamName, typeClass.sym, typeClass.sym.info, {}) block addTypeParam: for prev in typeParams: diff --git a/compiler/suggest.nim b/compiler/suggest.nim index ba70de1f7..23aecfa71 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -106,7 +106,7 @@ proc cmpSuggestions(a, b: Suggest): int = # independent of hashing order: result = cmp(a.name.s, b.name.s) -proc symToSuggest(s: PSym, isLocal: bool, section: IdeCmd, info: TLineInfo; +proc symToSuggest(conf: ConfigRef; s: PSym, isLocal: bool, section: IdeCmd, info: TLineInfo; quality: range[0..100]; prefix: PrefixMatch; inTypeContext: bool; scope: int): Suggest = new(result) @@ -125,7 +125,7 @@ proc symToSuggest(s: PSym, isLocal: bool, section: IdeCmd, info: TLineInfo; if u.fileIndex == info.fileIndex: inc c result.localUsages = c result.symkind = s.kind - if optIdeTerse notin gGlobalOptions: + if optIdeTerse notin conf.globalOptions: result.qualifiedPath = @[] if not isLocal and s.kind != skModule: let ow = s.owner @@ -237,7 +237,7 @@ proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} = proc suggestField(c: PContext, s: PSym; f: PNode; info: TLineInfo; outputs: var Suggestions) = var pm: PrefixMatch if filterSym(s, f, pm) and fieldVisible(c, s): - outputs.add(symToSuggest(s, isLocal=true, ideSug, info, 100, pm, c.inTypeContext > 0, 0)) + outputs.add(symToSuggest(c.config, s, isLocal=true, ideSug, info, 100, pm, c.inTypeContext > 0, 0)) proc getQuality(s: PSym): range[0..100] = if s.typ != nil and s.typ.len > 1: @@ -256,7 +256,7 @@ template wholeSymTab(cond, section: untyped) = let it {.inject.} = item var pm {.inject.}: PrefixMatch if cond: - outputs.add(symToSuggest(it, isLocal = isLocal, section, info, getQuality(it), + outputs.add(symToSuggest(c.config, it, isLocal = isLocal, section, info, getQuality(it), pm, c.inTypeContext > 0, scopeN)) proc suggestSymList(c: PContext, list, f: PNode; info: TLineInfo, outputs: var Suggestions) = @@ -330,7 +330,7 @@ proc suggestEverything(c: PContext, n, f: PNode, outputs: var Suggestions) = for it in items(scope.symbols): var pm: PrefixMatch if filterSym(it, f, pm): - outputs.add(symToSuggest(it, isLocal = isLocal, ideSug, n.info, 0, pm, + outputs.add(symToSuggest(c.config, it, isLocal = isLocal, ideSug, n.info, 0, pm, c.inTypeContext > 0, scopeN)) #if scope == c.topLevelScope and f.isNil: break @@ -352,8 +352,8 @@ proc suggestFieldAccess(c: PContext, n, field: PNode, outputs: var Suggestions) else: for it in items(n.sym.tab): if filterSym(it, field, pm): - outputs.add(symToSuggest(it, isLocal=false, ideSug, n.info, 100, pm, c.inTypeContext > 0, -100)) - outputs.add(symToSuggest(m, isLocal=false, ideMod, n.info, 100, PrefixMatch.None, + outputs.add(symToSuggest(c.config, it, isLocal=false, ideSug, n.info, 100, pm, c.inTypeContext > 0, -100)) + outputs.add(symToSuggest(c.config, m, isLocal=false, ideMod, n.info, 100, PrefixMatch.None, c.inTypeContext > 0, -99)) if typ == nil: @@ -363,11 +363,11 @@ proc suggestFieldAccess(c: PContext, n, field: PNode, outputs: var Suggestions) # all symbols accessible, because we are in the current module: for it in items(c.topLevelScope.symbols): if filterSym(it, field, pm): - outputs.add(symToSuggest(it, isLocal=false, ideSug, n.info, 100, pm, c.inTypeContext > 0, -99)) + outputs.add(symToSuggest(c.config, it, isLocal=false, ideSug, n.info, 100, pm, c.inTypeContext > 0, -99)) else: for it in items(n.sym.tab): if filterSym(it, field, pm): - outputs.add(symToSuggest(it, isLocal=false, ideSug, n.info, 100, pm, c.inTypeContext > 0, -99)) + outputs.add(symToSuggest(c.config, it, isLocal=false, ideSug, n.info, 100, pm, c.inTypeContext > 0, -99)) else: # fallback: suggestEverything(c, n, field, outputs) @@ -426,29 +426,29 @@ when defined(nimsuggest): s.allUsages.add(info) var - lastLineInfo*: TLineInfo + lastLineInfo*: TLineInfo # XXX global here -proc findUsages(info: TLineInfo; s: PSym; usageSym: var PSym) = +proc findUsages(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym) = if suggestVersion == 1: if usageSym == nil and isTracked(info, s.name.s.len): usageSym = s - suggestResult(symToSuggest(s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0)) + suggestResult(symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0)) elif s == usageSym: if lastLineInfo != info: - suggestResult(symToSuggest(s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0)) + suggestResult(symToSuggest(conf, s, isLocal=false, ideUse, info, 100, PrefixMatch.None, false, 0)) lastLineInfo = info when defined(nimsuggest): - proc listUsages*(s: PSym) = + proc listUsages*(conf: ConfigRef; s: PSym) = #echo "usages ", len(s.allUsages) for info in s.allUsages: let x = if info == s.info and info.col == s.info.col: ideDef else: ideUse - suggestResult(symToSuggest(s, isLocal=false, x, info, 100, PrefixMatch.None, false, 0)) + suggestResult(symToSuggest(conf, s, isLocal=false, x, info, 100, PrefixMatch.None, false, 0)) -proc findDefinition(info: TLineInfo; s: PSym) = +proc findDefinition(conf: ConfigRef; info: TLineInfo; s: PSym) = if s.isNil: return if isTracked(info, s.name.s.len): - suggestResult(symToSuggest(s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0)) + suggestResult(symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0)) suggestQuit() proc ensureIdx[T](x: var T, y: int) = @@ -467,18 +467,18 @@ proc suggestSym*(conf: ConfigRef; info: TLineInfo; s: PSym; usageSym: var PSym; s.addNoDup(info) if conf.ideCmd == ideUse: - findUsages(info, s, usageSym) + findUsages(conf, info, s, usageSym) elif conf.ideCmd == ideDef: - findDefinition(info, s) + findDefinition(conf, info, s) elif conf.ideCmd == ideDus and s != nil: if isTracked(info, s.name.s.len): - suggestResult(symToSuggest(s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0)) - findUsages(info, s, usageSym) + suggestResult(symToSuggest(conf, s, isLocal=false, ideDef, info, 100, PrefixMatch.None, false, 0)) + findUsages(conf, info, s, usageSym) elif conf.ideCmd == ideHighlight and info.fileIndex == gTrackPos.fileIndex: - suggestResult(symToSuggest(s, isLocal=false, ideHighlight, info, 100, PrefixMatch.None, false, 0)) + suggestResult(symToSuggest(conf, s, isLocal=false, ideHighlight, info, 100, PrefixMatch.None, false, 0)) elif conf.ideCmd == ideOutline and info.fileIndex == gTrackPos.fileIndex and isDecl: - suggestResult(symToSuggest(s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0)) + suggestResult(symToSuggest(conf, s, isLocal=false, ideOutline, info, 100, PrefixMatch.None, false, 0)) proc warnAboutDeprecated(conf: ConfigRef; info: TLineInfo; s: PSym) = if s.kind in routineKinds: @@ -587,7 +587,7 @@ proc suggestSentinel*(c: PContext) = for it in items(scope.symbols): var pm: PrefixMatch if filterSymNoOpr(it, nil, pm): - outputs.add(symToSuggest(it, isLocal = isLocal, ideSug, newLineInfo(gTrackPos.fileIndex, -1, -1), 0, PrefixMatch.None, false, scopeN)) + outputs.add(symToSuggest(c.config, it, isLocal = isLocal, ideSug, newLineInfo(gTrackPos.fileIndex, -1, -1), 0, PrefixMatch.None, false, scopeN)) dec(c.compilesContextId) produceOutput(outputs, c.config) diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim index 4a6474912..18d68bd2d 100644 --- a/compiler/syntaxes.nim +++ b/compiler/syntaxes.nim @@ -119,7 +119,7 @@ proc applyFilter(p: var TParsers, n: PNode, filename: string, if f != filtNone: if hintCodeBegin in p.config.notes: rawMessage(p.config, hintCodeBegin, []) - msgWriteln(result.s) + msgWriteln(p.config, result.s) rawMessage(p.config, hintCodeEnd, []) proc evalPipe(p: var TParsers, n: PNode, filename: string, diff --git a/compiler/transf.nim b/compiler/transf.nim index e49d51b11..a10e8a1e5 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -358,7 +358,7 @@ proc transformYield(c: PTransf, n: PNode): PTransNode = proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode = result = transformSons(c, n) - if gCmd == cmdCompileToCpp or sfCompileToCpp in c.module.flags: return + if c.graph.config.cmd == cmdCompileToCpp or sfCompileToCpp in c.module.flags: return var n = result.PNode case n.sons[0].kind of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64: @@ -390,7 +390,7 @@ proc generateThunk(c: PTransf; prc: PNode, dest: PType): PNode = # we cannot generate a proper thunk here for GC-safety reasons # (see internal documentation): - if gCmd == cmdCompileToJS: return prc + if c.graph.config.cmd == cmdCompileToJS: return prc result = newNodeIT(nkClosure, prc.info, dest) var conv = newNodeIT(nkHiddenSubConv, prc.info, dest) conv.add(emptyNode) @@ -716,7 +716,7 @@ proc transformCall(c: PTransf, n: PNode): PTransNode = proc transformExceptBranch(c: PTransf, n: PNode): PTransNode = result = transformSons(c, n) - if n[0].isInfixAs() and (not isImportedException(n[0][1].typ)): + if n[0].isInfixAs() and not isImportedException(n[0][1].typ, c.graph.config): let excTypeNode = n[0][1] let actions = newTransNode(nkStmtListExpr, n[1], 2) # Generating `let exc = (excType)(getCurrentException())` -- cgit 1.4.1-2-gfad0