From 554908df0cc80d8a983a5fccdc8951094c38b180 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Thu, 6 Jun 2019 21:58:25 +0100 Subject: [PATCH 01/25] Create FUNDING.yml --- .github/FUNDING.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..06dd755365 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: 'nim' # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: 'https://nim-lang.org/donate.html' # Replace with a single custom sponsorship URL From 447cc1ff09c877c5cab380cdabdfba446a5cafe7 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 7 Jun 2019 10:37:00 +0200 Subject: [PATCH 02/25] nimpretty: fixes #10295 --- compiler/layouter.nim | 14 +++++++++----- compiler/parser.nim | 2 ++ nimpretty/tests/exhaustive.nim | 9 +++++++++ nimpretty/tests/expected/exhaustive.nim | 10 ++++++++++ 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/compiler/layouter.nim b/compiler/layouter.nim index 6cb129fc1e..94664f41c3 100644 --- a/compiler/layouter.nim +++ b/compiler/layouter.nim @@ -106,11 +106,15 @@ proc softLinebreak(em: var Emitter, lit: string) = # +2 because we blindly assume a comma or ' &' might follow if not em.inquote and em.col+lit.len+2 >= MaxLineLen: if em.lastTok in splitters: - while em.content.len > 0 and em.content[em.content.high] == ' ': - setLen(em.content, em.content.len-1) - wr("\L") - em.col = 0 - for i in 1..em.indentLevel+moreIndent(em): wr(" ") + # bug #10295, check first if even more indentation would help: + let spaces = em.indentLevel+moreIndent(em) + if spaces < em.col: + let oldPos = em.content.len # we can undo our changes if not benefitial + while em.content.len > 0 and em.content[em.content.high] == ' ': + setLen(em.content, em.content.len-1) + wr("\L") + em.col = 0 + for i in 1..spaces: wr(" ") else: # search backwards for a good split position: for a in mitems(em.altSplitPos): diff --git a/compiler/parser.nim b/compiler/parser.nim index c154e5eb09..2db7c7c913 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -96,6 +96,8 @@ proc getTok(p: var TParser) = p.hasProgress = true when defined(nimpretty2): emitTok(p.em, p.lex, p.tok) + # skip the additional tokens that nimpretty needs but the parser has no + # interest in: while p.tok.tokType == tkComment: rawGetTok(p.lex, p.tok) emitTok(p.em, p.lex, p.tok) diff --git a/nimpretty/tests/exhaustive.nim b/nimpretty/tests/exhaustive.nim index 2903a59afa..b8042af065 100644 --- a/nimpretty/tests/exhaustive.nim +++ b/nimpretty/tests/exhaustive.nim @@ -366,3 +366,12 @@ proc fun4() = var i = 0 while i/dev/null | openssl x509 -noout -dates") + +let res = execProcess("echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates") diff --git a/nimpretty/tests/expected/exhaustive.nim b/nimpretty/tests/expected/exhaustive.nim index cd3d136e7a..91a2e90273 100644 --- a/nimpretty/tests/expected/exhaustive.nim +++ b/nimpretty/tests/expected/exhaustive.nim @@ -375,3 +375,13 @@ proc fun4() = var i = 0 while i < a.len and i < a.len: return + + +# bug #10295 + +import osproc +let res = execProcess( + "echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates") + +let res = execProcess( + "echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates") From 5a3722410257598d7b07c7b6c719a225a53dbe37 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 7 Jun 2019 10:49:56 +0200 Subject: [PATCH 03/25] develop version is 0.20.99 [feature] --- changelog.md | 263 +------------------------------------------------ lib/system.nim | 2 +- 2 files changed, 2 insertions(+), 263 deletions(-) diff --git a/changelog.md b/changelog.md index 9ddfd36dcc..87032fc0e3 100644 --- a/changelog.md +++ b/changelog.md @@ -1,294 +1,33 @@ -## v0.20.0 - 2019-06-06 +## v0.20.2 - XXXX-XX-XX ### Changes affecting backwards compatibility -- `shr` is now sign preserving. Use `-d:nimOldShiftRight` to enable - the old behavior globally. - -- The ``isLower``, ``isUpper`` family of procs in strutils/unicode - operating on **strings** have been - deprecated since it was unclear what these do. Note that the much more - useful procs that operate on ``char`` or ``Rune`` are not affected. - -- `strutils.editDistance` has been deprecated, - use `editdistance.editDistance` or `editdistance.editDistanceAscii` - instead. - -- The OpenMP parallel iterator \``||`\` now supports any `#pragma omp directive` - and not just `#pragma omp parallel for`. See - [OpenMP documentation](https://www.openmp.org/wp-content/uploads/OpenMP-4.5-1115-CPP-web.pdf). - - The default annotation is `parallel for`, if you used OpenMP without annotation - the change is transparent, if you used annotations you will have to prefix - your previous annotations with `parallel for`. - - Furthermore, an overload with positive stepping is available. - -- The `unchecked` pragma was removed, instead use `system.UncheckedArray`. - -- The undocumented ``#? strongSpaces`` parsing mode has been removed. - -- The `not` operator is now always a unary operator, this means that code like - ``assert not isFalse(3)`` compiles. - -- `getImpl` on a `var` or `let` symbol will now return the full `IdentDefs` - tree from the symbol declaration instead of just the initializer portion. - -- Methods are now ordinary "single" methods, only the first parameter is - used to select the variant at runtime. For backwards compatibility - use the new `--multimethods:on` switch. - -- Generic methods are now deprecated; they never worked well. - -- Compile time checks for integer and float conversions are now stricter. - For example, `const x = uint32(-1)` now gives a compile time error instead - of being equivalent to `const x = 0xFFFFFFFF'u32`. - -- Using `typed` as the result type in templates/macros now means - "expression with a type". The old meaning of `typed` is preserved - as `void` or no result type at all. - -- A bug allowed `macro foo(): int = 123` to compile even though a - macro has to return a `NimNode`. This has been fixed. - -- With the exception of `uint` and `uint64`, conversion to unsigned types - are now range checked during runtime. - -- Macro arguments of type `typedesc` are now passed to the macro as - `NimNode` like every other type except `static`. Use `typed` for a - behavior that is identical in new and old - Nim. See the RFC [Pass typedesc as NimNode to macros](https://github.com/nim-lang/RFCs/issues/148) - for more details. - #### Breaking changes in the standard library -- `osproc.execProcess` now also takes a `workingDir` parameter. - -- `std/sha1.secureHash` now accepts `openArray[char]`, not `string`. (Former - successful matches should keep working, though former failures will not.) - -- `options.UnpackError` is no longer a ref type and inherits from `system.Defect` - instead of `system.ValueError`. - -- `system.ValueError` now inherits from `system.CatchableError` instead of `system.Defect`. - -- The procs `parseutils.parseBiggestInt`, `parseutils.parseInt`, - `parseutils.parseBiggestUInt` and `parseutils.parseUInt` now raise a - `ValueError` when the parsed integer is outside of the valid range. - Previously they sometimes raised an `OverflowError` and sometimes they - returned `0`. - -- The procs `parseutils.parseBin`, `parseutils.parseOct` and `parseutils.parseHex` - were not clearing their `var` parameter `number` and used to push its value to - the left when storing the parsed string into it. Now they always set the value - of the parameter to `0` before storing the result of the parsing, unless the - string to parse is not valid (then the value of `number` is not changed). - -- `streams.StreamObject` now restricts its fields to only raise `system.Defect`, - `system.IOError` and `system.OSError`. - This change only affects custom stream implementations. - -- nre's `RegexMatch.{captureBounds,captures}[]` no longer return `Option` or - `nil`/`""`, respectively. Use the newly added `n in p.captures` method to - check if a group is captured, otherwise you'll receive an exception. - -- nre's `RegexMatch.{captureBounds,captures}.toTable` no longer accept a - default parameter. Instead uncaptured entries are left empty. Use - `Table.getOrDefault()` if you need defaults. - -- nre's `RegexMatch.captures.{items,toSeq}` now returns an `Option[string]` - instead of a `string`. With the removal of `nil` strings, this is the only - way to indicate a missing match. Inside your loops, instead - of `capture == ""` or `capture == nil`, use `capture.isSome` to check if a capture is - present, and `capture.get` to get its value. - -- nre's `replace()` no longer throws `ValueError` when the replacement string - has missing captures. It instead throws `KeyError` for named captures, and - `IndexError` for unnamed captures. This is consistent with - `RegexMatch.{captureBounds,captures}[]`. - -- `splitFile` now correctly handles edge cases, see #10047. - -- `isNil` is no longer false for undefined in the JavaScript backend: - now it's true for both nil and undefined. - Use `isNull` or `isUndefined` if you need exact equality: - `isNil` is consistent with `===`, `isNull` and `isUndefined` with `==`. - -- several deprecated modules were removed: `ssl`, `matchers`, `httpserver`, - `unsigned`, `actors`, `parseurl` - -- two poorly documented and not used modules (`subexes`, `scgi`) were moved to - graveyard (they are available as Nimble packages) - -- procs `string.add(int)` and `string.add(float)` which implicitly convert - ints and floats to string have been deprecated. - Use `string.addInt(int)` and `string.addFloat(float)` instead. - -- ``case object`` branch transitions via ``system.reset`` are deprecated. - Compile your code with ``-d:nimOldCaseObjects`` for a transition period. - -- base64 module: The default parameter `newLine` for the `encode` procs - was changed from `"\13\10"` to the empty string `""`. - #### Breaking changes in the compiler -- The compiler now implements the "generic symbol prepass" for `when` statements - in generics, see bug #8603. This means that code like this does not compile - anymore: - -```nim -proc enumToString*(enums: openArray[enum]): string = - # typo: 'e' instead 'enums' - when e.low.ord >= 0 and e.high.ord < 256: - result = newString(enums.len) - else: - result = newString(enums.len * 2) -``` - -- ``discard x`` is now illegal when `x` is a function symbol. - -- Implicit imports via ``--import: module`` in a config file are now restricted - to the main package. - ### Library additions -- There is a new stdlib module `std/editdistance` as a replacement for the - deprecated `strutils.editDistance`. - -- There is a new stdlib module `std/wordwrap` as a replacement for the - deprecated `strutils.wordwrap`. - -- Added `split`, `splitWhitespace`, `size`, `alignLeft`, `align`, - `strip`, `repeat` procs and iterators to `unicode.nim`. - -- Added `or` for `NimNode` in `macros`. - -- Added `system.typeof` for more control over how `type` expressions - can be deduced. - -- Added `macros.isInstantiationOf` for checking if the proc symbol - is instantiation of generic proc symbol. - -- Added the parameter ``isSorted`` for the ``sequtils.deduplicate`` proc. - -- There is a new stdlib module `std/diff` to compute the famous "diff" - of two texts by line. - -- Added `os.relativePath`. - -- Added `parseopt.remainingArgs`. - -- Added `os.getCurrentCompilerExe` (implemented as `getAppFilename` at CT), - can be used to retrieve the currently executing compiler. - -- Added `xmltree.toXmlAttributes`. - -- Added ``std/sums`` module for fast summation functions. - -- Added `Rusage`, `getrusage`, `wait4` to the posix interface. - -- Added the `posix_utils` module. - -- Added `system.default`. - -- Added `sequtils.items` for closure iterators, allows closure iterators - to be used by the `mapIt`, `filterIt`, `allIt`, `anyIt`, etc. - ### Library changes -- The string output of `macros.lispRepr` proc has been tweaked - slightly. The `dumpLisp` macro in this module now outputs an - indented proper Lisp, devoid of commas. - -- Added `macros.signatureHash` that returns a stable identifier - derived from the signature of a symbol. - -- In `strutils` empty strings now no longer matched as substrings - anymore. - -- The `Complex` type is now a generic object and not a tuple anymore. - -- The `ospaths` module is now deprecated, use `os` instead. Note that - `os` is available in a NimScript environment but unsupported - operations produce a compile-time error. - -- The `parseopt` module now supports a new flag `allowWhitespaceAfterColon` - (default value: true) that can be set to `false` for better Posix - interoperability. (Bug #9619.) - -- `os.joinPath` and `os.normalizePath` handle edge cases like ``"a/b/../../.."`` - differently. - -- `securehash` was moved to `lib/deprecated`. - -- The switch ``-d:useWinAnsi`` is not supported anymore. - -- In `times` module, procs `format` and `parse` accept a new optional - `DateTimeLocale` argument for formatting/parsing dates in other languages. ### Language additions -- Vm support for float32<->int32 and float64<->int64 casts was added. -- There is a new pragma block `noSideEffect` that works like - the `gcsafe` pragma block. -- added `os.getCurrentProcessId`. -- User defined pragmas are now allowed in the pragma blocks. -- Pragma blocks are no longer eliminated from the typed AST tree to preserve - pragmas for further analysis by macros. -- Custom pragmas are now supported for `var` and `let` symbols. -- Tuple unpacking is now supported for constants and for loop variables. -- Case object branches can be initialized with a runtime discriminator if - possible discriminator values are constrained within a case statement. - ### Language changes -- The standard extension for SCF (source code filters) files was changed from - ``.tmpl`` to ``.nimf``, - it's more recognizable and allows tools like Github to recognize it as Nim, - see [#9647](https://github.com/nim-lang/Nim/issues/9647). - The previous extension will continue to work. - -- Pragma syntax is now consistent. Previous syntax where type pragmas did not - follow the type name is now deprecated. Also pragma before generic parameter - list is deprecated to be consistent with how pragmas are used with a proc. See - [#8514](https://github.com/nim-lang/Nim/issues/8514) and - [#1872](https://github.com/nim-lang/Nim/issues/1872) for further details. - -- Hash sets and tables are initialized by default. The explicit `initHashSet`, - `initTable`, etc. are not needed anymore. - ### Tool changes -- `jsondoc` now includes a `moduleDescription` field with the module - description. `jsondoc0` shows comments as its own objects as shown in the - documentation. -- `nimpretty`: --backup now defaults to `off` instead of `on` and the flag was - undocumented; use `git` instead of relying on backup files. -- `koch` now defaults to build the latest *stable* Nimble version unless you - explicitly ask for the latest master version via `--latest`. ### Compiler changes -- The deprecated `fmod` proc is now unavailable on the VM. -- A new `--outdir` option was added. -- The compiled JavaScript file for the project produced by executing `nim js` - will no longer be placed in the nimcache directory. -- The `--hotCodeReloading` has been implemented for the native targets. - The compiler also provides a new more flexible API for handling the - hot code reloading events in the code. -- The compiler now supports a ``--expandMacro:macroNameHere`` switch - for easy introspection into what a macro expands into. -- The `-d:release` switch now does not disable runtime checks anymore. - For a release build that also disables runtime checks - use `-d:release -d:danger` or simply `-d:danger`. ### Bugfixes diff --git a/lib/system.nim b/lib/system.nim index 4b15a18828..fb2e504a09 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -3454,7 +3454,7 @@ const NimMinor* {.intdefine.}: int = 20 ## is the minor number of Nim's version. - NimPatch* {.intdefine.}: int = 0 + NimPatch* {.intdefine.}: int = 99 ## is the patch number of Nim's version. NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch From 790bc5b07bd192d4ddd2bcd08179e8cd82236f55 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 7 Jun 2019 11:50:56 +0200 Subject: [PATCH 04/25] nimpretty: fixes #10177 [bugfix] --- compiler/layouter.nim | 107 +++++++++++++++--------- nimpretty/tests/exhaustive.nim | 9 ++ nimpretty/tests/expected/exhaustive.nim | 9 ++ 3 files changed, 85 insertions(+), 40 deletions(-) diff --git a/compiler/layouter.nim b/compiler/layouter.nim index 94664f41c3..ddcb5a9762 100644 --- a/compiler/layouter.nim +++ b/compiler/layouter.nim @@ -24,6 +24,10 @@ type SemicolonKind = enum detectSemicolonKind, useSemicolon, dontTouch + LayoutToken = enum + ltSpaces, ltNewline, ltComment, ltLit, ltKeyword, ltExportMarker, ltIdent, + ltOther, ltOpr + Emitter* = object config: ConfigRef fid: FileIndex @@ -34,6 +38,7 @@ type keepIndents*: int doIndentMore*: int content: string + kinds: seq[LayoutToken] indentStack: seq[int] fixedUntil: int # marks where we must not go in the content altSplitPos: array[SplitKind, int] # alternative split positions @@ -79,10 +84,29 @@ proc calcCol(em: var Emitter; s: string) = dec i inc em.col -template wr(x) = +proc wr(em: var Emitter; x: string; lt: LayoutToken) = em.content.add x + em.kinds.add lt inc em.col, x.len +when false: + proc wrNewline(em: var Emitter) = + em.tokens.add "\L" + em.kinds.add ltNewline + inc em.tokensSum, 1 + em.col = 0 + + proc wrSpaces(em: var Emitter; spaces: Natural) = + wr(em, strutils.repeat(' ', spaces), ltSpaces) + + proc removeSpaces(em: var Emitter) = + while em.kinds.len > 0 and em.kinds[^1] == ltSpaces: + let tokenLen = em.tokens[^1].len + setLen(em.tokens, em.tokens.len-1) + setLen(em.kinds, em.kinds.len-1) + dec em.tokensSum, tokenLen + dec em.col, tokenLen + template goodCol(col): bool = col in 40..MaxLineLen const @@ -109,12 +133,11 @@ proc softLinebreak(em: var Emitter, lit: string) = # bug #10295, check first if even more indentation would help: let spaces = em.indentLevel+moreIndent(em) if spaces < em.col: - let oldPos = em.content.len # we can undo our changes if not benefitial while em.content.len > 0 and em.content[em.content.high] == ' ': setLen(em.content, em.content.len-1) - wr("\L") + wr(em, "\L", ltNewline) em.col = 0 - for i in 1..spaces: wr(" ") + for i in 1..spaces: wr(em, " ", ltSpaces) else: # search backwards for a good split position: for a in mitems(em.altSplitPos): @@ -136,28 +159,31 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = template endsInAlpha(em): bool = em.content.len > 0 and em.content[em.content.high] in SymChars+{'_'} + template wasExportMarker(em): bool = + em.kinds.len > 0 and em.kinds[^1] == ltExportMarker + proc emitComment(em: var Emitter; tok: TToken) = let lit = strip fileSection(em.config, em.fid, tok.commentOffsetA, tok.commentOffsetB) em.lineSpan = countNewlines(lit) if em.lineSpan > 0: calcCol(em, lit) if not endsInWhite(em): - wr(" ") + wr(em, " ", ltSpaces) if em.lineSpan == 0 and max(em.col, LineCommentColumn) + lit.len <= MaxLineLen: - for i in 1 .. LineCommentColumn - em.col: wr(" ") - wr lit + for i in 1 .. LineCommentColumn - em.col: wr(em, " ", ltSpaces) + wr em, lit, ltComment if tok.tokType == tkComment and tok.literal.startsWith("#!nimpretty"): case tok.literal of "#!nimpretty off": inc em.keepIndents - wr("\L") + wr(em, "\L", ltNewline) em.lastLineNumber = tok.line + 1 of "#!nimpretty on": dec em.keepIndents em.lastLineNumber = tok.line - wr("\L") + wr(em, "\L", ltNewline) #for i in 1 .. tok.indent: wr " " - wr tok.literal + wr em, tok.literal, ltComment em.col = 0 em.lineSpan = 0 return @@ -192,49 +218,49 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = # remove trailing whitespace: while em.content.len > 0 and em.content[em.content.high] == ' ': setLen(em.content, em.content.len-1) - wr("\L") - for i in 2..tok.line - em.lastLineNumber: wr("\L") + wr(em, "\L", ltNewline) + for i in 2..tok.line - em.lastLineNumber: wr(em, "\L", ltNewline) em.col = 0 for i in 1..em.indentLevel: - wr(" ") + wr(em, " ", ltSpaces) em.fixedUntil = em.content.high var lastTokWasTerse = false case tok.tokType of tokKeywordLow..tokKeywordHigh: if endsInAlpha(em): - wr(" ") + wr(em, " ", ltSpaces) elif not em.inquote and not endsInWhite(em) and em.lastTok notin openPars and not em.lastTokWasTerse: #and tok.tokType in oprSet - wr(" ") + wr(em, " ", ltSpaces) if not em.inquote: - wr(TokTypeToStr[tok.tokType]) + wr(em, TokTypeToStr[tok.tokType], ltKeyword) case tok.tokType of tkAnd: rememberSplit(splitAnd) of tkOr: rememberSplit(splitOr) of tkIn, tkNotin: rememberSplit(splitIn) - wr(" ") + wr(em, " ", ltSpaces) else: discard else: # keywords in backticks are not normalized: - wr(tok.ident.s) + wr(em, tok.ident.s, ltIdent) of tkColon: - wr(TokTypeToStr[tok.tokType]) - wr(" ") + wr(em, TokTypeToStr[tok.tokType], ltOther) + wr(em, " ", ltSpaces) of tkSemicolon, tkComma: - wr(TokTypeToStr[tok.tokType]) + wr(em, TokTypeToStr[tok.tokType], ltOther) rememberSplit(splitComma) - wr(" ") + wr(em, " ", ltSpaces) of tkParDotLe, tkParLe, tkBracketDotLe, tkBracketLe, tkCurlyLe, tkCurlyDotLe, tkBracketLeColon: - if tok.strongSpaceA > 0 and not em.endsInWhite: - wr(" ") - wr(TokTypeToStr[tok.tokType]) + if tok.strongSpaceA > 0 and not em.endsInWhite and not em.wasExportMarker: + wr(em, " ", ltSpaces) + wr(em, TokTypeToStr[tok.tokType], ltOther) rememberSplit(splitParLe) of tkParRi, tkBracketRi, tkCurlyRi, @@ -242,33 +268,33 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = tkCurlyDotRi, tkParDotRi, tkColonColon: - wr(TokTypeToStr[tok.tokType]) + wr(em, TokTypeToStr[tok.tokType], ltOther) of tkDot: lastTokWasTerse = true - wr(TokTypeToStr[tok.tokType]) + wr(em, TokTypeToStr[tok.tokType], ltOther) of tkEquals: - if not em.inquote and not em.endsInWhite: wr(" ") - wr(TokTypeToStr[tok.tokType]) - if not em.inquote: wr(" ") + if not em.inquote and not em.endsInWhite: wr(em, " ", ltSpaces) + wr(em, TokTypeToStr[tok.tokType], ltOther) + if not em.inquote: wr(em, " ", ltSpaces) of tkOpr, tkDotDot: if ((tok.strongSpaceA == 0 and tok.strongSpaceB == 0) or em.inquote) and tok.ident.s notin ["<", ">", "<=", ">=", "==", "!="]: # bug #9504: remember to not spacify a keyword: lastTokWasTerse = true # if not surrounded by whitespace, don't produce any whitespace either: - wr(tok.ident.s) + wr(em, tok.ident.s, ltOpr) else: - if not em.endsInWhite: wr(" ") - wr(tok.ident.s) + if not em.endsInWhite: wr(em, " ", ltSpaces) + wr(em, tok.ident.s, ltOpr) template isUnary(tok): bool = tok.strongSpaceB == 0 and tok.strongSpaceA > 0 if not isUnary(tok): rememberSplit(splitBinary) - wr(" ") + wr(em, " ", ltSpaces) of tkAccent: - if not em.inquote and endsInAlpha(em): wr(" ") - wr(TokTypeToStr[tok.tokType]) + if not em.inquote and endsInAlpha(em): wr(em, " ", ltSpaces) + wr(em, TokTypeToStr[tok.tokType], ltOther) em.inquote = not em.inquote of tkComment: if not preventComment: @@ -276,16 +302,16 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = of tkIntLit..tkStrLit, tkRStrLit, tkTripleStrLit, tkGStrLit, tkGTripleStrLit, tkCharLit: let lit = fileSection(em.config, em.fid, tok.offsetA, tok.offsetB) softLinebreak(em, lit) - if endsInAlpha(em) and tok.tokType notin {tkGStrLit, tkGTripleStrLit}: wr(" ") + if endsInAlpha(em) and tok.tokType notin {tkGStrLit, tkGTripleStrLit}: wr(em, " ", ltSpaces) em.lineSpan = countNewlines(lit) if em.lineSpan > 0: calcCol(em, lit) - wr lit + wr em, lit, ltLit of tkEof: discard else: let lit = if tok.ident != nil: tok.ident.s else: tok.literal softLinebreak(em, lit) - if endsInAlpha(em): wr(" ") - wr lit + if endsInAlpha(em): wr(em, " ", ltSpaces) + wr em, lit, ltIdent em.lastTok = tok.tokType em.lastTokWasTerse = lastTokWasTerse @@ -293,6 +319,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = em.lineSpan = 0 proc starWasExportMarker*(em: var Emitter) = + em.kinds[^1] = ltExportMarker if em.content.endsWith(" * "): setLen(em.content, em.content.len-3) em.content.add("*") diff --git a/nimpretty/tests/exhaustive.nim b/nimpretty/tests/exhaustive.nim index b8042af065..b8ef26a0c7 100644 --- a/nimpretty/tests/exhaustive.nim +++ b/nimpretty/tests/exhaustive.nim @@ -375,3 +375,12 @@ let res = execProcess( "echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates") let res = execProcess("echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates") + + +# bug #10177 + +proc foo * () = + discard + +proc foo* [T]() = + discard diff --git a/nimpretty/tests/expected/exhaustive.nim b/nimpretty/tests/expected/exhaustive.nim index 91a2e90273..7847737147 100644 --- a/nimpretty/tests/expected/exhaustive.nim +++ b/nimpretty/tests/expected/exhaustive.nim @@ -385,3 +385,12 @@ let res = execProcess( let res = execProcess( "echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -dates") + + +# bug #10177 + +proc foo*() = + discard + +proc foo*[T]() = + discard From 667af87e66ed1ad4f3dbe455df72257d21fbc426 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 7 Jun 2019 12:59:31 +0200 Subject: [PATCH 05/25] nimpretty: fixes #9505 [bugfix] --- compiler/layouter.nim | 10 +++++++++- nimpretty/tests/expected/wrong_ind.nim | 24 ++++++++++++++++++++++++ nimpretty/tests/wrong_ind.nim | 24 ++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 nimpretty/tests/expected/wrong_ind.nim create mode 100644 nimpretty/tests/wrong_ind.nim diff --git a/compiler/layouter.nim b/compiler/layouter.nim index ddcb5a9762..336b09fa71 100644 --- a/compiler/layouter.nim +++ b/compiler/layouter.nim @@ -113,6 +113,10 @@ const openPars = {tkParLe, tkParDotLe, tkBracketLe, tkBracketLeColon, tkCurlyDotLe, tkCurlyLe} + closedPars = {tkParRi, tkParDotRi, + tkBracketRi, tkCurlyDotRi, + tkCurlyRi} + splitters = openPars + {tkComma, tkSemicolon} oprSet = {tkOpr, tkDiv, tkMod, tkShl, tkShr, tkIn, tkNotin, tkIs, tkIsnot, tkNot, tkOf, tkAs, tkDotDot, tkAnd, tkOr, tkXor} @@ -196,8 +200,12 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = em.fixedUntil = em.content.high elif tok.indent >= 0: - if em.lastTok in (splitters + oprSet) or em.keepIndents > 0: + if em.keepIndents > 0: em.indentLevel = tok.indent + elif (em.lastTok in (splitters + oprSet) and tok.tokType notin closedPars): + # aka: we are in an expression context: + let alignment = tok.indent - em.indentStack[^1] + em.indentLevel = alignment + em.indentStack.high * em.indWidth else: if tok.indent > em.indentStack[^1]: em.indentStack.add tok.indent diff --git a/nimpretty/tests/expected/wrong_ind.nim b/nimpretty/tests/expected/wrong_ind.nim new file mode 100644 index 0000000000..a21e94618d --- /dev/null +++ b/nimpretty/tests/expected/wrong_ind.nim @@ -0,0 +1,24 @@ + +# bug #9505 + +import std/[ + strutils, ospaths, os +] +import pkg/[ + regex +] + +proc fun() = + let a = [ + 1, + 2, + ] + discard + +proc funB() = + let a = [ + 1, + 2, + 3 + ] + discard diff --git a/nimpretty/tests/wrong_ind.nim b/nimpretty/tests/wrong_ind.nim new file mode 100644 index 0000000000..0559673f89 --- /dev/null +++ b/nimpretty/tests/wrong_ind.nim @@ -0,0 +1,24 @@ + +# bug #9505 + +import std/[ + strutils, ospaths, os +] +import pkg/[ + regex +] + +proc fun() = + let a = [ + 1, + 2, + ] + discard + +proc funB() = + let a = [ + 1, + 2, + 3 + ] + discard From 12fc1dfb2ccb8409fbfe17898e173e8629dbf095 Mon Sep 17 00:00:00 2001 From: Araq Date: Fri, 7 Jun 2019 13:03:04 +0200 Subject: [PATCH 06/25] nimpretty: closes #10159 [bugfix] --- nimpretty/tests/exhaustive.nim | 12 ++++++++++++ nimpretty/tests/expected/exhaustive.nim | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/nimpretty/tests/exhaustive.nim b/nimpretty/tests/exhaustive.nim index b8ef26a0c7..2677c86bfb 100644 --- a/nimpretty/tests/exhaustive.nim +++ b/nimpretty/tests/exhaustive.nim @@ -384,3 +384,15 @@ proc foo * () = proc foo* [T]() = discard + + +# bug #10159 + +proc fun() = + discard + +proc main() = + echo "foo"; echo "bar"; + discard + +main() diff --git a/nimpretty/tests/expected/exhaustive.nim b/nimpretty/tests/expected/exhaustive.nim index 7847737147..0e27e32a46 100644 --- a/nimpretty/tests/expected/exhaustive.nim +++ b/nimpretty/tests/expected/exhaustive.nim @@ -394,3 +394,15 @@ proc foo*() = proc foo*[T]() = discard + + +# bug #10159 + +proc fun() = + discard + +proc main() = + echo "foo"; echo "bar"; + discard + +main() From 99a4fed96b4e703ff490edfaa65e0832ad41ce34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Fri, 7 Jun 2019 14:34:59 +0200 Subject: [PATCH 07/25] fix for passing tuples as static params to macros (#11423); fixes #10751 [bugfix] * add vm value preparation proc * small optimization --- compiler/vm.nim | 23 ++++++++++++++++++++--- tests/macros/tmacros1.nim | 12 ++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/compiler/vm.nim b/compiler/vm.nim index e1e75135a6..a2af0e7b88 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -2031,12 +2031,29 @@ proc evalStaticStmt*(module: PSym; g: ModuleGraph; e: PNode, prc: PSym) = proc setupCompileTimeVar*(module: PSym; g: ModuleGraph; n: PNode) = discard evalConstExprAux(module, g, nil, n, emStaticStmt) +proc prepareVMValue(arg: PNode): PNode = + ## strip nkExprColonExpr from tuple values recurively. That is how + ## they are expected to be stored in the VM. + + # Early abort without copy. No transformation takes place. + if arg.kind in nkLiterals: + return arg + + result = copyNode(arg) + if arg.kind == nkTupleConstr: + for child in arg: + if child.kind == nkExprColonExpr: + result.add prepareVMValue(child[1]) + else: + result.add prepareVMValue(child) + else: + for child in arg: + result.add prepareVMValue(child) + proc setupMacroParam(x: PNode, typ: PType): TFullReg = case typ.kind of tyStatic: - putIntoReg(result, x) - #of tyTypeDesc: - # putIntoReg(result, x) + putIntoReg(result, prepareVMValue(x)) else: result.kind = rkNode var n = x diff --git a/tests/macros/tmacros1.nim b/tests/macros/tmacros1.nim index a50465e1cf..706281d133 100644 --- a/tests/macros/tmacros1.nim +++ b/tests/macros/tmacros1.nim @@ -49,3 +49,15 @@ myEnums = enumerators2() echo myEnums myEnums = enumerators3() echo myEnums + +#10751 + +type Tuple = tuple + a: string + b: int + +macro foo(t: static Tuple): untyped = + doAssert t.a == "foo" + doAssert t.b == 12345 + +foo((a: "foo", b: 12345)) From 2c03c9f42e882eaff4f8e8fa358b9c66ecdd803a Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Fri, 7 Jun 2019 16:21:01 +0200 Subject: [PATCH 08/25] updates the contributing guidelines [other] --- doc/contributing.rst | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/contributing.rst b/doc/contributing.rst index c240cb80ed..317fe3ab7c 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -343,12 +343,10 @@ The Git stuff General commit rules -------------------- -1. Bugfixes that should be backported to the latest stable release should - contain the string ``[backport]`` in the commit message! There will be an - outmated process relying on these. However, bugfixes also have the inherent - risk of causing regressions which are worse for a "stable, bugfixes-only" - branch, so in doubt, leave out the ``[backport]``. Standard library bugfixes - are less critical than compiler bugfixes. +1. The commit message should contain either ``[bugfix]`` or ``[feature]`` + or ``[refactoring]`` or ``[other]``. Refactorings and bugfixes and "other" + are backported to the latest stable release branch (currently 0.20.x). + Refactorings are backported because they often enable further bugfixes. 2. All changes introduced by the commit (diff lines) must be related to the subject of the commit. From 9f82e07b2dc2ea89e1e35d5ec470fae84eab66b4 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 8 Jun 2019 00:00:00 +0200 Subject: [PATCH 09/25] nimpretty: fixes #10156 [bugfix] --- compiler/layouter.nim | 31 +++++++++++++++- nimpretty/tests/expected/wrong_ind.nim | 49 ++++++++++++++++++++++++++ nimpretty/tests/wrong_ind.nim | 49 ++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 1 deletion(-) diff --git a/compiler/layouter.nim b/compiler/layouter.nim index 336b09fa71..0b88a4aea9 100644 --- a/compiler/layouter.nim +++ b/compiler/layouter.nim @@ -156,6 +156,31 @@ proc softLinebreak(em: var Emitter, lit: string) = a = -1 break +proc emitMultilineComment(em: var Emitter, lit: string, col: int) = + # re-align every line in the multi-line comment: + var i = 0 + var lastIndent = em.indentStack[^1] + var b = 0 + for commentLine in splitLines(lit): + let stripped = commentLine.strip() + var a = 0 + while a < commentLine.len and commentLine[a] == ' ': inc a + if i == 0: + discard + elif stripped.len == 0: + wr em, "\L", ltNewline + else: + if a > lastIndent: + b += em.indWidth + lastIndent = a + elif a < lastIndent: + b -= em.indWidth + lastIndent = a + wr em, "\L", ltNewline + for i in 1 .. col + b: wr(em, " ", ltSpaces) + wr em, stripped, ltComment + inc i + proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = template endsInWhite(em): bool = @@ -167,6 +192,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = em.kinds.len > 0 and em.kinds[^1] == ltExportMarker proc emitComment(em: var Emitter; tok: TToken) = + let col = em.col let lit = strip fileSection(em.config, em.fid, tok.commentOffsetA, tok.commentOffsetB) em.lineSpan = countNewlines(lit) if em.lineSpan > 0: calcCol(em, lit) @@ -174,7 +200,10 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = wr(em, " ", ltSpaces) if em.lineSpan == 0 and max(em.col, LineCommentColumn) + lit.len <= MaxLineLen: for i in 1 .. LineCommentColumn - em.col: wr(em, " ", ltSpaces) - wr em, lit, ltComment + if em.lineSpan == 0: + wr em, lit, ltComment + else: + emitMultilineComment(em, lit, col) if tok.tokType == tkComment and tok.literal.startsWith("#!nimpretty"): case tok.literal diff --git a/nimpretty/tests/expected/wrong_ind.nim b/nimpretty/tests/expected/wrong_ind.nim index a21e94618d..9855e0c4d7 100644 --- a/nimpretty/tests/expected/wrong_ind.nim +++ b/nimpretty/tests/expected/wrong_ind.nim @@ -22,3 +22,52 @@ proc funB() = 3 ] discard + + +# bug #10156 +proc foo = + ## Comment 1 + ## Comment 2 + discard + +proc bar = + ## Comment 3 + ## Comment 4 + ## More here. + discard + + +proc barB = + # Comment 5 + # Comment 6 + discard + + +var x: int = 2 + +echo x +# bug #9144 + +proc a() = + if cond: + while true: + discard + # comment 1 + # end while + #end if + + # comment 2 + #if + #case + #end case + #end if + discard + + +proc a() = + while true: + discard + # comment 1 + + # comment 2 + discard diff --git a/nimpretty/tests/wrong_ind.nim b/nimpretty/tests/wrong_ind.nim index 0559673f89..eaa561b516 100644 --- a/nimpretty/tests/wrong_ind.nim +++ b/nimpretty/tests/wrong_ind.nim @@ -22,3 +22,52 @@ proc funB() = 3 ] discard + + +# bug #10156 +proc foo = + ## Comment 1 + ## Comment 2 + discard + +proc bar = + ## Comment 3 + ## Comment 4 + ## More here. + discard + + +proc barB = + # Comment 5 + # Comment 6 + discard + + +var x: int = 2 + +echo x +# bug #9144 + +proc a() = + if cond: + while true: + discard + # comment 1 + # end while + #end if + + # comment 2 + #if + #case + #end case + #end if + discard + + +proc a() = + while true: + discard + # comment 1 + + # comment 2 + discard From bf63d83a9759b6764a0b78b424f4635af35d743f Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 8 Jun 2019 00:13:57 +0200 Subject: [PATCH 10/25] update the nimc.rst document about the release/danger split [bugfix] --- doc/nimc.rst | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/doc/nimc.rst b/doc/nimc.rst index d291992ff1..4f5808cd24 100644 --- a/doc/nimc.rst +++ b/doc/nimc.rst @@ -132,8 +132,8 @@ Through the ``-d:x`` or ``--define:x`` switch you can define compile time symbols for conditional compilation. The defined switches can be checked in source code with the `when statement `_ and `defined proc `_. The typical use of this switch is to -enable builds in release mode (``-d:release``) where certain safety checks are -omitted for better performance. Another common use is the ``-d:ssl`` switch to +enable builds in release mode (``-d:release``) where optimizations are +enabled for better performance. Another common use is the ``-d:ssl`` switch to activate SSL sockets. Additionally, you may pass a value along with the symbol: ``-d:x=y`` @@ -169,6 +169,10 @@ The default build of a project is a `debug build`:idx:. To compile a nim c -d:release myproject.nim + To compile a `dangerous release build`:idx: define the ``danger`` symbol:: + + nim c -d:danger myproject.nim + Search path handling -------------------- @@ -344,10 +348,10 @@ complete list. ====================== ========================================================= Define Effect ====================== ========================================================= -``release`` Turns off runtime checks and turns on the optimizer. +``release`` Turns on the optimizer. More aggressive optimizations are possible, eg: ``--passC:-ffast-math`` (but see issue #10305) - ``--stacktrace:off`` +``danger`` Turns off all runtime checks and turns on the optimizer. ``useFork`` Makes ``osproc`` use ``fork`` instead of ``posix_spawn``. ``useNimRtl`` Compile and link against ``nimrtl.dll``. ``useMalloc`` Makes Nim use C's `malloc`:idx: instead of Nim's From bf9f1f7b45a4fa04cf7995c95af88680b2710f8c Mon Sep 17 00:00:00 2001 From: Miran Date: Sat, 8 Jun 2019 00:34:11 +0200 Subject: [PATCH 11/25] [bugfix] hashes: fix regression for nested containers (#11426) Move forward declarations earlier. --- lib/pure/hashes.nim | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim index df29dc0802..c8b9f0e069 100644 --- a/lib/pure/hashes.nim +++ b/lib/pure/hashes.nim @@ -149,6 +149,12 @@ proc hash*(x: float): Hash {.inline.} = var y = x + 1.0 result = cast[ptr Hash](addr(y))[] + +# Forward declarations before methods that hash containers. This allows +# containers to contain other containers +proc hash*[A](x: openArray[A]): Hash +proc hash*[A](x: set[A]): Hash + template bytewiseHashing(result: Hash, x: typed, start, stop: int) = for i in start .. stop: result = result !& hash(x[i]) @@ -292,12 +298,6 @@ proc hashIgnoreCase*(sBuf: string, sPos, ePos: int): Hash = result = !$h -# Forward declarations before methods that hash containers. This allows -# containers to contain other containers -proc hash*[A](x: openArray[A]): Hash -proc hash*[A](x: set[A]): Hash - - proc hash*[T: tuple](x: T): Hash = ## Efficient hashing of tuples. for f in fields(x): From bce908f6ee9f24346641310d8f7f8971e92ffe01 Mon Sep 17 00:00:00 2001 From: nc-x Date: Sat, 8 Jun 2019 04:07:08 +0530 Subject: [PATCH 12/25] fix `koch docs` failing at io.nim with `import os` in config.nims (#11418) [bugfix] --- lib/system.nim | 5 ++--- lib/system/io.nim.cfg | 1 - 2 files changed, 2 insertions(+), 4 deletions(-) delete mode 100644 lib/system/io.nim.cfg diff --git a/lib/system.nim b/lib/system.nim index fb2e504a09..d22585c6ab 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -4450,9 +4450,8 @@ when defined(genode): import system/widestrs export widestrs -when not defined(nimnoio): - import system/io - export io +import system/io +export io when not defined(createNimHcr): include nimhcr diff --git a/lib/system/io.nim.cfg b/lib/system/io.nim.cfg deleted file mode 100644 index fd7cc755ce..0000000000 --- a/lib/system/io.nim.cfg +++ /dev/null @@ -1 +0,0 @@ ---define: nimnoio From 3c62d4146899cd27f8926563fb071ea7db981899 Mon Sep 17 00:00:00 2001 From: Kaushal Modi Date: Sun, 9 Jun 2019 02:54:15 -0400 Subject: [PATCH 13/25] Make -d:tempDir switch work once again [bugfix] (#11442) Fixes https://github.com/nim-lang/Nim/issues/11441. --- lib/pure/os.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 8a185e81c0..aa58fea735 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -798,12 +798,13 @@ proc getTempDir*(): string {.rtl, extern: "nos$1", ## * `expandTilde proc <#expandTilde,string>`_ ## * `getCurrentDir proc <#getCurrentDir>`_ ## * `setCurrentDir proc <#setCurrentDir,string>`_ + const tempDirDefault = "/tmp/" when defined(tempDir): - const tempDir {.strdefine.}: string = nil + const tempDir {.strdefine.}: string = tempDirDefault return tempDir elif defined(windows): return string(getEnv("TEMP")) & "\\" elif defined(android): return getHomeDir() - else: return "/tmp/" + else: return tempDirDefault proc expandTilde*(path: string): string {. tags: [ReadEnvEffect, ReadIOEffect].} = From 8317de76486d8d7652c2fdeaa444e01bd6f17151 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 9 Jun 2019 09:18:19 +0200 Subject: [PATCH 14/25] complex.nim: reformating [other] --- lib/pure/complex.nim | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim index 69d9c0f7f4..442bf62dbb 100644 --- a/lib/pure/complex.nim +++ b/lib/pure/complex.nim @@ -7,10 +7,6 @@ # distribution, for details about the copyright. # - - - - ## This module implements complex numbers. ## Complex numbers are currently implemented as generic on a 64-bit or 32-bit float. @@ -42,8 +38,8 @@ proc complex64*(re: float64; im: float64 = 0.0): Complex[float64] = template im*(arg: typedesc[float32]): Complex32 = complex[float32](0, 1) template im*(arg: typedesc[float64]): Complex64 = complex[float64](0, 1) -template im*(arg : float32): Complex32 = complex[float32](0, arg) -template im*(arg : float64): Complex64 = complex[float64](0, arg) +template im*(arg: float32): Complex32 = complex[float32](0, arg) +template im*(arg: float64): Complex64 = complex[float64](0, arg) proc abs*[T](z: Complex[T]): T = ## Return the distance from (0,0) to ``z``. From cb47e49d3bceb616b26bb3dc7bc0ec1a34927013 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sun, 9 Jun 2019 22:22:36 +0200 Subject: [PATCH 15/25] nimpretty: keep a seq of tokens instead of a single string to enable better transformations [refactoring] --- compiler/layouter.nim | 162 +++++++++++++++++++++++------------------- 1 file changed, 90 insertions(+), 72 deletions(-) diff --git a/compiler/layouter.nim b/compiler/layouter.nim index 0b88a4aea9..7ada05e873 100644 --- a/compiler/layouter.nim +++ b/compiler/layouter.nim @@ -12,6 +12,7 @@ import idents, lexer, lineinfos, llstream, options, msgs, strutils, pathutils from os import changeFileExt +from sequtils import delete const MaxLineLen = 80 @@ -37,8 +38,8 @@ type col, lastLineNumber, lineSpan, indentLevel, indWidth*: int keepIndents*: int doIndentMore*: int - content: string kinds: seq[LayoutToken] + tokens: seq[string] indentStack: seq[int] fixedUntil: int # marks where we must not go in the content altSplitPos: array[SplitKind, int] # alternative split positions @@ -55,21 +56,25 @@ proc openEmitter*(em: var Emitter, cache: IdentCache; em.lastTok = tkInvalid em.inquote = false em.col = 0 - em.content = newStringOfCap(16_000) em.indentStack = newSeqOfCap[int](30) em.indentStack.add 0 em.lastLineNumber = 1 proc closeEmitter*(em: var Emitter) = let outFile = em.config.absOutFile - if fileExists(outFile) and readFile(outFile.string) == em.content: + + var content = newStringOfCap(16_000) + for i in 0..em.tokens.high: + content.add em.tokens[i] + + if fileExists(outFile) and readFile(outFile.string) == content: discard "do nothing, see #9499" return var f = llStreamOpen(outFile, fmWrite) if f == nil: rawMessage(em.config, errGenerated, "cannot open file: " & outFile.string) return - f.llStreamWrite em.content + f.llStreamWrite content llStreamClose(f) proc countNewlines(s: string): int = @@ -85,27 +90,29 @@ proc calcCol(em: var Emitter; s: string) = inc em.col proc wr(em: var Emitter; x: string; lt: LayoutToken) = - em.content.add x + em.tokens.add x em.kinds.add lt inc em.col, x.len + assert em.tokens.len == em.kinds.len -when false: - proc wrNewline(em: var Emitter) = - em.tokens.add "\L" - em.kinds.add ltNewline - inc em.tokensSum, 1 - em.col = 0 +proc wrNewline(em: var Emitter) = + em.tokens.add "\L" + em.kinds.add ltNewline + em.col = 0 - proc wrSpaces(em: var Emitter; spaces: Natural) = +proc wrSpaces(em: var Emitter; spaces: int) = + if spaces > 0: wr(em, strutils.repeat(' ', spaces), ltSpaces) - proc removeSpaces(em: var Emitter) = - while em.kinds.len > 0 and em.kinds[^1] == ltSpaces: - let tokenLen = em.tokens[^1].len - setLen(em.tokens, em.tokens.len-1) - setLen(em.kinds, em.kinds.len-1) - dec em.tokensSum, tokenLen - dec em.col, tokenLen +proc wrSpace(em: var Emitter) = + wr(em, " ", ltSpaces) + +proc removeSpaces(em: var Emitter) = + while em.kinds.len > 0 and em.kinds[^1] == ltSpaces: + let tokenLen = em.tokens[^1].len + setLen(em.tokens, em.tokens.len-1) + setLen(em.kinds, em.kinds.len-1) + dec em.col, tokenLen template goodCol(col): bool = col in 40..MaxLineLen @@ -123,7 +130,7 @@ const template rememberSplit(kind) = if goodCol(em.col): - em.altSplitPos[kind] = em.content.len + em.altSplitPos[kind] = em.tokens.len template moreIndent(em): int = (if em.doIndentMore > 0: em.indWidth*2 else: em.indWidth) @@ -137,22 +144,31 @@ proc softLinebreak(em: var Emitter, lit: string) = # bug #10295, check first if even more indentation would help: let spaces = em.indentLevel+moreIndent(em) if spaces < em.col: - while em.content.len > 0 and em.content[em.content.high] == ' ': - setLen(em.content, em.content.len-1) - wr(em, "\L", ltNewline) + removeSpaces em + wrNewline(em) em.col = 0 - for i in 1..spaces: wr(em, " ", ltSpaces) + wrSpaces em, spaces else: # search backwards for a good split position: for a in mitems(em.altSplitPos): if a > em.fixedUntil: var spaces = 0 - while a+spaces < em.content.len and em.content[a+spaces] == ' ': + while a+spaces < em.kinds.len and em.kinds[a+spaces] == ltSpaces: inc spaces - if spaces > 0: delete(em.content, a, a+spaces-1) - em.col = em.content.len - a - let ws = "\L" & repeat(' ', em.indentLevel+moreIndent(em)) - em.content.insert(ws, a) + if spaces > 0: + delete(em.tokens, a, a+spaces-1) + delete(em.kinds, a, a+spaces-1) + em.kinds.insert(ltNewline, a) + em.tokens.insert("\L", a) + em.kinds.insert(ltSpaces, a+1) + em.tokens.insert(repeat(' ', em.indentLevel+moreIndent(em)), a+1) + # recompute em.col: + var i = em.kinds.len-1 + em.col = 0 + while i >= 0 and em.kinds[i] != ltNewline: + inc em.col, em.tokens[i].len + dec i + # mark position as "already split here" a = -1 break @@ -168,7 +184,7 @@ proc emitMultilineComment(em: var Emitter, lit: string, col: int) = if i == 0: discard elif stripped.len == 0: - wr em, "\L", ltNewline + wrNewline em else: if a > lastIndent: b += em.indWidth @@ -176,17 +192,17 @@ proc emitMultilineComment(em: var Emitter, lit: string, col: int) = elif a < lastIndent: b -= em.indWidth lastIndent = a - wr em, "\L", ltNewline - for i in 1 .. col + b: wr(em, " ", ltSpaces) + wrNewline em + wrSpaces em, col + b wr em, stripped, ltComment inc i proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = template endsInWhite(em): bool = - em.content.len == 0 or em.content[em.content.high] in {' ', '\L'} + em.kinds.len == 0 or em.kinds[em.kinds.high] in {ltSpaces, ltNewline} template endsInAlpha(em): bool = - em.content.len > 0 and em.content[em.content.high] in SymChars+{'_'} + em.tokens.len > 0 and em.tokens[em.tokens.high][^1] in SymChars+{'_'} template wasExportMarker(em): bool = em.kinds.len > 0 and em.kinds[^1] == ltExportMarker @@ -197,9 +213,9 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = em.lineSpan = countNewlines(lit) if em.lineSpan > 0: calcCol(em, lit) if not endsInWhite(em): - wr(em, " ", ltSpaces) + wrSpace em if em.lineSpan == 0 and max(em.col, LineCommentColumn) + lit.len <= MaxLineLen: - for i in 1 .. LineCommentColumn - em.col: wr(em, " ", ltSpaces) + wrSpaces em, LineCommentColumn - em.col if em.lineSpan == 0: wr em, lit, ltComment else: @@ -209,13 +225,12 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = case tok.literal of "#!nimpretty off": inc em.keepIndents - wr(em, "\L", ltNewline) + wrNewline em em.lastLineNumber = tok.line + 1 of "#!nimpretty on": dec em.keepIndents em.lastLineNumber = tok.line - wr(em, "\L", ltNewline) - #for i in 1 .. tok.indent: wr " " + wrNewline em wr em, tok.literal, ltComment em.col = 0 em.lineSpan = 0 @@ -226,7 +241,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = # we have an inline comment so handle it before the indentation token: emitComment(em, tok) preventComment = true - em.fixedUntil = em.content.high + em.fixedUntil = em.tokens.high elif tok.indent >= 0: if em.keepIndents > 0: @@ -253,24 +268,21 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = is not touched. ]# # remove trailing whitespace: - while em.content.len > 0 and em.content[em.content.high] == ' ': - setLen(em.content, em.content.len-1) - wr(em, "\L", ltNewline) - for i in 2..tok.line - em.lastLineNumber: wr(em, "\L", ltNewline) - em.col = 0 - for i in 1..em.indentLevel: - wr(em, " ", ltSpaces) - em.fixedUntil = em.content.high + removeSpaces em + wrNewline em + for i in 2..tok.line - em.lastLineNumber: wrNewline(em) + wrSpaces em, em.indentLevel + em.fixedUntil = em.tokens.high var lastTokWasTerse = false case tok.tokType of tokKeywordLow..tokKeywordHigh: if endsInAlpha(em): - wr(em, " ", ltSpaces) + wrSpace em elif not em.inquote and not endsInWhite(em) and em.lastTok notin openPars and not em.lastTokWasTerse: #and tok.tokType in oprSet - wr(em, " ", ltSpaces) + wrSpace em if not em.inquote: wr(em, TokTypeToStr[tok.tokType], ltKeyword) @@ -280,7 +292,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = of tkOr: rememberSplit(splitOr) of tkIn, tkNotin: rememberSplit(splitIn) - wr(em, " ", ltSpaces) + wrSpace em else: discard else: # keywords in backticks are not normalized: @@ -288,15 +300,15 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = of tkColon: wr(em, TokTypeToStr[tok.tokType], ltOther) - wr(em, " ", ltSpaces) + wrSpace em of tkSemicolon, tkComma: wr(em, TokTypeToStr[tok.tokType], ltOther) rememberSplit(splitComma) - wr(em, " ", ltSpaces) + wrSpace em of tkParDotLe, tkParLe, tkBracketDotLe, tkBracketLe, tkCurlyLe, tkCurlyDotLe, tkBracketLeColon: if tok.strongSpaceA > 0 and not em.endsInWhite and not em.wasExportMarker: - wr(em, " ", ltSpaces) + wrSpace em wr(em, TokTypeToStr[tok.tokType], ltOther) rememberSplit(splitParLe) of tkParRi, @@ -310,9 +322,9 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = lastTokWasTerse = true wr(em, TokTypeToStr[tok.tokType], ltOther) of tkEquals: - if not em.inquote and not em.endsInWhite: wr(em, " ", ltSpaces) + if not em.inquote and not em.endsInWhite: wrSpace(em) wr(em, TokTypeToStr[tok.tokType], ltOther) - if not em.inquote: wr(em, " ", ltSpaces) + if not em.inquote: wrSpace(em) of tkOpr, tkDotDot: if ((tok.strongSpaceA == 0 and tok.strongSpaceB == 0) or em.inquote) and tok.ident.s notin ["<", ">", "<=", ">=", "==", "!="]: @@ -321,16 +333,16 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = # if not surrounded by whitespace, don't produce any whitespace either: wr(em, tok.ident.s, ltOpr) else: - if not em.endsInWhite: wr(em, " ", ltSpaces) + if not em.endsInWhite: wrSpace(em) wr(em, tok.ident.s, ltOpr) template isUnary(tok): bool = tok.strongSpaceB == 0 and tok.strongSpaceA > 0 if not isUnary(tok): rememberSplit(splitBinary) - wr(em, " ", ltSpaces) + wrSpace(em) of tkAccent: - if not em.inquote and endsInAlpha(em): wr(em, " ", ltSpaces) + if not em.inquote and endsInAlpha(em): wrSpace(em) wr(em, TokTypeToStr[tok.tokType], ltOther) em.inquote = not em.inquote of tkComment: @@ -339,7 +351,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = of tkIntLit..tkStrLit, tkRStrLit, tkTripleStrLit, tkGStrLit, tkGTripleStrLit, tkCharLit: let lit = fileSection(em.config, em.fid, tok.offsetA, tok.offsetB) softLinebreak(em, lit) - if endsInAlpha(em) and tok.tokType notin {tkGStrLit, tkGTripleStrLit}: wr(em, " ", ltSpaces) + if endsInAlpha(em) and tok.tokType notin {tkGStrLit, tkGTripleStrLit}: wrSpace(em) em.lineSpan = countNewlines(lit) if em.lineSpan > 0: calcCol(em, lit) wr em, lit, ltLit @@ -347,7 +359,7 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = else: let lit = if tok.ident != nil: tok.ident.s else: tok.literal softLinebreak(em, lit) - if endsInAlpha(em): wr(em, " ", ltSpaces) + if endsInAlpha(em): wrSpace(em) wr em, lit, ltIdent em.lastTok = tok.tokType @@ -355,21 +367,27 @@ proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = em.lastLineNumber = tok.line + em.lineSpan em.lineSpan = 0 +proc endsWith(em: Emitter; k: varargs[string]): bool = + if em.tokens.len < k.len: return false + for i in 0..high(k): + if em.tokens[em.tokens.len - k.len + i] != k[i]: return false + return true + proc starWasExportMarker*(em: var Emitter) = - em.kinds[^1] = ltExportMarker - if em.content.endsWith(" * "): - setLen(em.content, em.content.len-3) - em.content.add("*") + if em.endsWith(" ", "*", " "): + setLen(em.tokens, em.tokens.len-3) + setLen(em.kinds, em.kinds.len-3) + em.tokens.add("*") + em.kinds.add ltExportMarker dec em.col, 2 proc commaWasSemicolon*(em: var Emitter) = if em.semicolons == detectSemicolonKind: - em.semicolons = if em.content.endsWith(", "): dontTouch else: useSemicolon - if em.semicolons == useSemicolon and em.content.endsWith(", "): - setLen(em.content, em.content.len-2) - em.content.add("; ") + em.semicolons = if em.endsWith(",", " "): dontTouch else: useSemicolon + if em.semicolons == useSemicolon and em.endsWith(",", " "): + em.tokens[em.tokens.len-2] = ";" proc curlyRiWasPragma*(em: var Emitter) = - if em.content.endsWith("}"): - setLen(em.content, em.content.len-1) - em.content.add(".}") + if em.endsWith("}"): + em.tokens[em.tokens.len-1] = ".}" + inc em.col From 22a1b1203829acabe618102e7295a116315e1bf0 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Mon, 10 Jun 2019 04:31:57 -0300 Subject: [PATCH 16/25] [documentation] fix #11281, httpclient examples (#11455) --- lib/pure/httpclient.nim | 49 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 83cf77a1b1..4139d83fd3 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -121,12 +121,59 @@ ## if however data does not reach the client within the specified timeout a ## ``TimeoutError`` exception will be raised. ## +## Here is how to set a timeout when creating an ``HttpClient`` instance: +## +## .. code-block:: Nim +## import httpclient +## +## let client = newHttpClient(timeout = 42) +## ## Proxy ## ===== ## ## A proxy can be specified as a param to any of the procedures defined in ## this module. To do this, use the ``newProxy`` constructor. Unfortunately, ## only basic authentication is supported at the moment. +## +## Some examples on how to configure a Proxy for ``HttpClient``: +## +## .. code-block:: Nim +## import httpclient +## +## let myProxy = newProxy("http://myproxy.network") +## let client = newHttpClient(proxy = myProxy) +## +## Get Proxy URL from environment variables: +## +## .. code-block:: Nim +## import httpclient +## +## var url = "" +## try: +## if existsEnv("http_proxy"): +## url = getEnv("http_proxy") +## elif existsEnv("https_proxy"): +## url = getEnv("https_proxy") +## except ValueError: +## echo "Unable to parse proxy from environment variables." +## +## let myProxy = newProxy(url = url) +## let client = newHttpClient(proxy = myProxy) +## +## Redirects +## ========= +## +## The maximum redirects can be set with the ``maxRedirects`` of ``int`` type, +## it specifies the maximum amount of redirects to follow, +## it defaults to ``5``, you can set it to ``0`` to disable redirects. +## +## Here you can see an example about how to set the ``maxRedirects`` of ``HttpClient``: +## +## .. code-block:: Nim +## import httpclient +## +## let client = newHttpClient(maxRedirects = 0) +## import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes, math, random, httpcore, times, tables, streams @@ -647,7 +694,7 @@ proc getSocket*(client: HttpClient): Socket = ## ## .. code-block:: Nim ## if client.connected: - ## echo client.getSocket.getLocalAddr + ## echo client.getSocket.getLocalAddr ## echo client.getSocket.getPeerAddr ## return client.socket From caf93f43554475e36f0526fc6212963338b02cdf Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Mon, 10 Jun 2019 10:50:02 +0200 Subject: [PATCH 17/25] nimpretty: smart tabs support, fixes #9399 [bugfix] --- compiler/layouter.nim | 114 +++++++++++++++++++----- compiler/parser.nim | 55 +++++++----- nimpretty/nimpretty.nim | 14 ++- nimpretty/nimpretty.nim.cfg | 1 - nimpretty/tests/exhaustive.nim | 13 +++ nimpretty/tests/expected/exhaustive.nim | 21 ++++- 6 files changed, 159 insertions(+), 59 deletions(-) diff --git a/compiler/layouter.nim b/compiler/layouter.nim index 7ada05e873..3ac907f1d1 100644 --- a/compiler/layouter.nim +++ b/compiler/layouter.nim @@ -16,7 +16,6 @@ from sequtils import delete const MaxLineLen = 80 - LineCommentColumn = 30 type SplitKind = enum @@ -26,8 +25,10 @@ type detectSemicolonKind, useSemicolon, dontTouch LayoutToken = enum - ltSpaces, ltNewline, ltComment, ltLit, ltKeyword, ltExportMarker, ltIdent, - ltOther, ltOpr + ltSpaces, ltNewline, ltTab, + ltComment, ltLit, ltKeyword, ltExportMarker, ltIdent, + ltOther, ltOpr, + ltBeginSection, ltEndSection Emitter* = object config: ConfigRef @@ -60,12 +61,59 @@ proc openEmitter*(em: var Emitter, cache: IdentCache; em.indentStack.add 0 em.lastLineNumber = 1 +proc computeMax(em: Emitter; pos: int): int = + var p = pos + result = 0 + while p < em.tokens.len and em.kinds[p] != ltEndSection: + var lhs = 0 + var lineLen = 0 + var foundTab = false + while p < em.tokens.len and em.kinds[p] != ltEndSection: + if em.kinds[p] == ltNewline: + if foundTab and lineLen <= MaxLineLen: result = max(result, lhs) + inc p + break + if em.kinds[p] == ltTab: + foundTab = true + else: + if not foundTab: + inc lhs, em.tokens[p].len + inc lineLen, em.tokens[p].len + inc p + +proc computeRhs(em: Emitter; pos: int): int = + var p = pos + result = 0 + while p < em.tokens.len and em.kinds[p] != ltNewline: + inc result, em.tokens[p].len + inc p + proc closeEmitter*(em: var Emitter) = let outFile = em.config.absOutFile var content = newStringOfCap(16_000) + var maxLhs = 0 + var lineLen = 0 + var lineBegin = 0 for i in 0..em.tokens.high: - content.add em.tokens[i] + case em.kinds[i] + of ltBeginSection: + maxLhs = computeMax(em, lineBegin) + of ltEndSection: + maxLhs = 0 + of ltTab: + if maxLhs == 0 or computeRhs(em, i)+maxLhs > MaxLineLen: + content.add ' ' + else: + let spaces = max(maxLhs - lineLen + 1, 1) + for j in 1..spaces: content.add ' ' + of ltNewline: + content.add em.tokens[i] + lineLen = 0 + lineBegin = i+1 + else: + content.add em.tokens[i] + inc lineLen, em.tokens[i].len if fileExists(outFile) and readFile(outFile.string) == content: discard "do nothing, see #9499" @@ -107,6 +155,12 @@ proc wrSpaces(em: var Emitter; spaces: int) = proc wrSpace(em: var Emitter) = wr(em, " ", ltSpaces) +proc wrTab(em: var Emitter) = + wr(em, " ", ltTab) + +proc beginSection*(em: var Emitter) = wr(em, "", ltBeginSection) +proc endSection*(em: var Emitter) = wr(em, "", ltEndSection) + proc removeSpaces(em: var Emitter) = while em.kinds.len > 0 and em.kinds[^1] == ltSpaces: let tokenLen = em.tokens[^1].len @@ -197,30 +251,42 @@ proc emitMultilineComment(em: var Emitter, lit: string, col: int) = wr em, stripped, ltComment inc i +proc lastChar(s: string): char = + result = if s.len > 0: s[s.high] else: '\0' + +proc endsInWhite(em: Emitter): bool = + var i = em.tokens.len-1 + while i >= 0 and em.kinds[i] in {ltBeginSection, ltEndSection}: dec(i) + result = if i >= 0: em.kinds[i] in {ltSpaces, ltNewline, ltTab} else: true + +proc endsInNewline(em: Emitter): bool = + var i = em.tokens.len-1 + while i >= 0 and em.kinds[i] in {ltBeginSection, ltEndSection, ltSpaces}: dec(i) + result = if i >= 0: em.kinds[i] in {ltNewline, ltTab} else: true + +proc endsInAlpha(em: Emitter): bool = + var i = em.tokens.len-1 + while i >= 0 and em.kinds[i] in {ltBeginSection, ltEndSection}: dec(i) + result = if i >= 0: em.tokens[i].lastChar in SymChars+{'_'} else: false + +proc emitComment(em: var Emitter; tok: TToken) = + let col = em.col + let lit = strip fileSection(em.config, em.fid, tok.commentOffsetA, tok.commentOffsetB) + em.lineSpan = countNewlines(lit) + if em.lineSpan > 0: calcCol(em, lit) + if em.lineSpan == 0: + if not endsInNewline(em): + wrTab em + wr em, lit, ltComment + else: + if not endsInWhite(em): + wrTab em + emitMultilineComment(em, lit, col) + proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) = - - template endsInWhite(em): bool = - em.kinds.len == 0 or em.kinds[em.kinds.high] in {ltSpaces, ltNewline} - template endsInAlpha(em): bool = - em.tokens.len > 0 and em.tokens[em.tokens.high][^1] in SymChars+{'_'} - template wasExportMarker(em): bool = em.kinds.len > 0 and em.kinds[^1] == ltExportMarker - proc emitComment(em: var Emitter; tok: TToken) = - let col = em.col - let lit = strip fileSection(em.config, em.fid, tok.commentOffsetA, tok.commentOffsetB) - em.lineSpan = countNewlines(lit) - if em.lineSpan > 0: calcCol(em, lit) - if not endsInWhite(em): - wrSpace em - if em.lineSpan == 0 and max(em.col, LineCommentColumn) + lit.len <= MaxLineLen: - wrSpaces em, LineCommentColumn - em.col - if em.lineSpan == 0: - wr em, lit, ltComment - else: - emitMultilineComment(em, lit, col) - if tok.tokType == tkComment and tok.literal.startsWith("#!nimpretty"): case tok.literal of "#!nimpretty off": diff --git a/compiler/parser.nim b/compiler/parser.nim index 2db7c7c913..eda75f9264 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -30,7 +30,7 @@ import llstream, lexer, idents, strutils, ast, astalgo, msgs, options, lineinfos, pathutils -when defined(nimpretty2): +when defined(nimpretty): import layouter type @@ -44,7 +44,7 @@ type inPragma*: int # Pragma level inSemiStmtList*: int emptyNode: PNode - when defined(nimpretty2): + when defined(nimpretty): em*: Emitter SymbolMode = enum @@ -89,12 +89,17 @@ proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode # implementation +template prettySection(body) = + when defined(nimpretty): beginSection(p.em) + body + when defined(nimpretty): endSection(p.em) + proc getTok(p: var TParser) = ## Get the next token from the parser's lexer, and store it in the parser's ## `tok` member. rawGetTok(p.lex, p.tok) p.hasProgress = true - when defined(nimpretty2): + when defined(nimpretty): emitTok(p.em, p.lex, p.tok) # skip the additional tokens that nimpretty needs but the parser has no # interest in: @@ -108,7 +113,7 @@ proc openParser*(p: var TParser, fileIdx: FileIndex, inputStream: PLLStream, ## initToken(p.tok) openLexer(p.lex, fileIdx, inputStream, cache, config) - when defined(nimpretty2): + when defined(nimpretty): openEmitter(p.em, cache, config, fileIdx) getTok(p) # read the first token p.firstTok = true @@ -121,7 +126,7 @@ proc openParser*(p: var TParser, filename: AbsoluteFile, inputStream: PLLStream, proc closeParser(p: var TParser) = ## Close a parser, freeing up its resources. closeLexer(p.lex) - when defined(nimpretty2): + when defined(nimpretty): closeEmitter(p.em) proc parMessage(p: TParser, msg: TMsgKind, arg = "") = @@ -384,7 +389,7 @@ proc exprColonEqExpr(p: var TParser): PNode = proc exprList(p: var TParser, endTok: TTokType, result: PNode) = #| exprList = expr ^+ comma - when defined(nimpretty2): + when defined(nimpretty): inc p.em.doIndentMore getTok(p) optInd(p, result) @@ -395,7 +400,7 @@ proc exprList(p: var TParser, endTok: TTokType, result: PNode) = if p.tok.tokType != tkComma: break getTok(p) optInd(p, a) - when defined(nimpretty2): + when defined(nimpretty): dec p.em.doIndentMore proc exprColonEqExprListAux(p: var TParser, endTok: TTokType, result: PNode) = @@ -830,10 +835,10 @@ proc simpleExprAux(p: var TParser, limit: int, mode: TPrimaryMode): PNode = result = parseOperators(p, result, limit, mode) proc simpleExpr(p: var TParser, mode = pmNormal): PNode = - when defined(nimpretty2): + when defined(nimpretty): inc p.em.doIndentMore result = simpleExprAux(p, -1, mode) - when defined(nimpretty2): + when defined(nimpretty): dec p.em.doIndentMore proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode = @@ -910,7 +915,7 @@ proc parsePragma(p: var TParser): PNode = skipComment(p, a) optPar(p) if p.tok.tokType in {tkCurlyDotRi, tkCurlyRi}: - when defined(nimpretty2): + when defined(nimpretty): if p.tok.tokType == tkCurlyRi: curlyRiWasPragma(p.em) getTok(p) else: @@ -922,7 +927,7 @@ proc identVis(p: var TParser; allowDot=false): PNode = #| identVisDot = symbol '.' optInd symbol opr? var a = parseSymbol(p) if p.tok.tokType == tkOpr: - when defined(nimpretty2): + when defined(nimpretty): starWasExportMarker(p.em) result = newNodeP(nkPostfix, p) addSon(result, newIdentNodeP(p.tok.ident, p)) @@ -1001,7 +1006,7 @@ proc parseTuple(p: var TParser, indentAllowed = false): PNode = var a = parseIdentColonEquals(p, {}) addSon(result, a) if p.tok.tokType notin {tkComma, tkSemiColon}: break - when defined(nimpretty2): + when defined(nimpretty): commaWasSemicolon(p.em) getTok(p) skipComment(p, a) @@ -1037,7 +1042,7 @@ proc parseParamList(p: var TParser, retColon = true): PNode = var a: PNode result = newNodeP(nkFormalParams, p) addSon(result, p.emptyNode) # return type - when defined(nimpretty2): + when defined(nimpretty): inc p.em.doIndentMore inc p.em.keepIndents let hasParLe = p.tok.tokType == tkParLe and p.tok.indent < 0 @@ -1059,7 +1064,7 @@ proc parseParamList(p: var TParser, retColon = true): PNode = break addSon(result, a) if p.tok.tokType notin {tkComma, tkSemiColon}: break - when defined(nimpretty2): + when defined(nimpretty): commaWasSemicolon(p.em) getTok(p) skipComment(p, a) @@ -1074,7 +1079,7 @@ proc parseParamList(p: var TParser, retColon = true): PNode = elif not retColon and not hasParle: # Mark as "not there" in order to mark for deprecation in the semantic pass: result = p.emptyNode - when defined(nimpretty2): + when defined(nimpretty): dec p.em.doIndentMore dec p.em.keepIndents @@ -1237,13 +1242,15 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode = else: result.kind = nkIteratorTy of tkEnum: if mode == pmTypeDef: - result = parseEnum(p) + prettySection: + result = parseEnum(p) else: result = newNodeP(nkEnumTy, p) getTok(p) of tkObject: if mode == pmTypeDef: - result = parseObject(p) + prettySection: + result = parseObject(p) else: result = newNodeP(nkObjectTy, p) getTok(p) @@ -1696,7 +1703,7 @@ proc parseGenericParamList(p: var TParser): PNode = var a = parseGenericParam(p) addSon(result, a) if p.tok.tokType notin {tkComma, tkSemiColon}: break - when defined(nimpretty2): + when defined(nimpretty): commaWasSemicolon(p.em) getTok(p) skipComment(p, a) @@ -2187,10 +2194,16 @@ proc complexOrSimpleStmt(p: var TParser): PNode = result = parseOperators(p, result, -1, pmNormal) else: result = parseSection(p, nkTypeSection, parseTypeDef) - of tkConst: result = parseSection(p, nkConstSection, parseConstant) - of tkLet: result = parseSection(p, nkLetSection, parseVariable) + of tkConst: + prettySection: + result = parseSection(p, nkConstSection, parseConstant) + of tkLet: + prettySection: + result = parseSection(p, nkLetSection, parseVariable) + of tkVar: + prettySection: + result = parseSection(p, nkVarSection, parseVariable) of tkWhen: result = parseIfOrWhen(p, nkWhenStmt) - of tkVar: result = parseSection(p, nkVarSection, parseVariable) of tkBind: result = parseBind(p, nkBindStmt) of tkMixin: result = parseBind(p, nkMixinStmt) of tkUsing: result = parseSection(p, nkUsingStmt, parseVariable) diff --git a/nimpretty/nimpretty.nim b/nimpretty/nimpretty.nim index 3e06ccff35..185f8da7c3 100644 --- a/nimpretty/nimpretty.nim +++ b/nimpretty/nimpretty.nim @@ -50,15 +50,11 @@ proc prettyPrint(infile, outfile: string, opt: PrettyOptions) = var conf = newConfigRef() let fileIdx = fileInfoIdx(conf, AbsoluteFile infile) conf.outFile = RelativeFile outfile - when defined(nimpretty2): - var p: TParsers - p.parser.em.indWidth = opt.indWidth - if setupParsers(p, fileIdx, newIdentCache(), conf): - discard parseAll(p) - closeParsers(p) - else: - let tree = parseFile(fileIdx, newIdentCache(), conf) - renderModule(tree, infile, outfile, {}, fileIdx, conf) + var p: TParsers + p.parser.em.indWidth = opt.indWidth + if setupParsers(p, fileIdx, newIdentCache(), conf): + discard parseAll(p) + closeParsers(p) proc main = var infile, outfile: string diff --git a/nimpretty/nimpretty.nim.cfg b/nimpretty/nimpretty.nim.cfg index b4fac53776..138bce52e2 100644 --- a/nimpretty/nimpretty.nim.cfg +++ b/nimpretty/nimpretty.nim.cfg @@ -1,3 +1,2 @@ --define: nimpretty ---define: nimpretty2 --define: nimOldCaseObjects diff --git a/nimpretty/tests/exhaustive.nim b/nimpretty/tests/exhaustive.nim index 2677c86bfb..2f8fe03f28 100644 --- a/nimpretty/tests/exhaustive.nim +++ b/nimpretty/tests/exhaustive.nim @@ -396,3 +396,16 @@ proc main() = discard main() + +type + TCallingConvention* = enum + ccDefault, # proc has no explicit calling convention + ccStdCall, # procedure is stdcall + ccCDecl, # cdecl + ccSafeCall, # safecall + ccSysCall, # system call + ccInline, # proc should be inlined + ccNoInline, # proc should not be inlined + ccFastCall, # fastcall (pass parameters in registers) + ccClosure, # proc has a closure + ccNoConvention # needed for generating proper C procs sometimes diff --git a/nimpretty/tests/expected/exhaustive.nim b/nimpretty/tests/expected/exhaustive.nim index 0e27e32a46..75580081d6 100644 --- a/nimpretty/tests/expected/exhaustive.nim +++ b/nimpretty/tests/expected/exhaustive.nim @@ -29,10 +29,10 @@ var x = 1 type GeneralTokenizer* = object of RootObj ## comment here - kind*: TokenClass ## and here - start*, length*: int ## you know how it goes... + kind*: TokenClass ## and here + start*, length*: int ## you know how it goes... buf: cstring - pos: int # other comment here. + pos: int # other comment here. state: TokenClass var x*: string @@ -122,7 +122,7 @@ type inquote {.pragmaHereWrongCurlyEnd.}: bool col, lastLineNumber, lineSpan, indentLevel: int content: string - fixedUntil: int # marks where we must not go in the content + fixedUntil: int # marks where we must not go in the content altSplitPos: array[SplitKind, int] # alternative split positions proc openEmitter*[T, S](em: var Emitter; config: ConfigRef; @@ -406,3 +406,16 @@ proc main() = discard main() + +type + TCallingConvention* = enum + ccDefault, # proc has no explicit calling convention + ccStdCall, # procedure is stdcall + ccCDecl, # cdecl + ccSafeCall, # safecall + ccSysCall, # system call + ccInline, # proc should be inlined + ccNoInline, # proc should not be inlined + ccFastCall, # fastcall (pass parameters in registers) + ccClosure, # proc has a closure + ccNoConvention # needed for generating proper C procs sometimes From 3a91a935847444956e40527d501ff3fb6553a7d6 Mon Sep 17 00:00:00 2001 From: Juan Carlos Date: Mon, 10 Jun 2019 05:53:34 -0300 Subject: [PATCH 18/25] Fixes #11431 (#11451) [bugfix] --- doc/basicopt.txt | 2 +- tools/nim.zsh-completion | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/basicopt.txt b/doc/basicopt.txt index aa6675dc8e..1405e7b01b 100644 --- a/doc/basicopt.txt +++ b/doc/basicopt.txt @@ -24,7 +24,7 @@ Options: -a, --assertions:on|off turn assertions 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) + --debugger:native Use native debugger (gdb) --app:console|gui|lib|staticlib generate a console app|GUI app|DLL|static library -r, --run run the compiled program with given arguments diff --git a/tools/nim.zsh-completion b/tools/nim.zsh-completion index e9b9002fb5..38ed93f736 100644 --- a/tools/nim.zsh-completion +++ b/tools/nim.zsh-completion @@ -63,7 +63,7 @@ _nim() { '*--opt=none[do not optimize]' \ '*--opt=speed[optimize for speed|size - use -d:release for a release build]' \ '*--opt=size[optimize for size]' \ - '*--debugger:native|endb[use native debugger (gdb) | ENDB (experimental)]' \ + '*--debugger:native[use native debugger (gdb)]' \ '*--app=console[generate a console app]' \ '*--app=gui[generate a GUI app]' \ '*--app=lib[generate a dynamic library]' \ From 7cf9b522b5d2735b5279e9c2bdcade5c177868f8 Mon Sep 17 00:00:00 2001 From: Miran Date: Mon, 10 Jun 2019 12:54:43 +0200 Subject: [PATCH 19/25] [bugfix] rename Nimrod to Nim, fix #11460 (#11462) --- config/nimdoc.tex.cfg | 2 +- doc/nimdoc.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config/nimdoc.tex.cfg b/config/nimdoc.tex.cfg index 599ede345a..76fef4afa4 100644 --- a/config/nimdoc.tex.cfg +++ b/config/nimdoc.tex.cfg @@ -39,7 +39,7 @@ $content """ doc.file = """ -% This file was generated by Nimrod. +% This file was generated by Nim. % Generated: $date $time UTC \documentclass[a4paper]{article} \usepackage[left=2cm,right=3cm,top=3cm,bottom=3cm]{geometry} diff --git a/doc/nimdoc.css b/doc/nimdoc.css index a002b6be1a..a8be5756b4 100644 --- a/doc/nimdoc.css +++ b/doc/nimdoc.css @@ -17,7 +17,7 @@ customize this style sheet. */ /* - Modified for the Nimrod Documenation by + Modified for the Nim Documenation by Andreas Rumpf */ From 94177f7357c3f67ea77b8fcf8ba1dbc0eb3f0423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arne=20D=C3=B6ring?= Date: Mon, 10 Jun 2019 19:58:11 +0200 Subject: [PATCH 20/25] VM can now cast integer type arbitrarily. (#11459) [feature] --- compiler/vmgen.nim | 46 +++++---------- tests/vm/tcastint.nim | 128 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 31 deletions(-) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 035ab25cdd..de314a552b 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -813,44 +813,28 @@ proc genCard(c: PCtx; n: PNode; dest: var TDest) = proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) = const allowedIntegers = {tyInt..tyInt64, tyUInt..tyUInt64, tyChar} - var signedIntegers = {tyInt8..tyInt32} - var unsignedIntegers = {tyUInt8..tyUInt32, tyChar} + var signedIntegers = {tyInt..tyInt64} + var unsignedIntegers = {tyUInt..tyUInt64, tyChar} let src = n.sons[1].typ.skipTypes(abstractRange)#.kind let dst = n.sons[0].typ.skipTypes(abstractRange)#.kind let src_size = getSize(c.config, src) let dst_size = getSize(c.config, dst) - if c.config.target.intSize < 8: - signedIntegers.incl(tyInt) - unsignedIntegers.incl(tyUInt) - if src_size == dst_size and src.kind in allowedIntegers and - dst.kind in allowedIntegers: + if src.kind in allowedIntegers and dst.kind in allowedIntegers: let tmp = c.genx(n.sons[1]) - var tmp2 = c.getTemp(n.sons[1].typ) - let tmp3 = c.getTemp(n.sons[1].typ) if dest < 0: dest = c.getTemp(n[0].typ) - proc mkIntLit(ival: int): int = - result = genLiteral(c, newIntTypeNode(nkIntLit, ival, getSysType(c.graph, n.info, tyInt))) - if src.kind in unsignedIntegers and dst.kind in signedIntegers: - # cast unsigned to signed integer of same size - # signedVal = (unsignedVal xor offset) -% offset - let offset = 1 shl (src_size * 8 - 1) - c.gABx(n, opcLdConst, tmp2, mkIntLit(offset)) - c.gABC(n, opcBitxorInt, tmp3, tmp, tmp2) - c.gABC(n, opcSubInt, dest, tmp3, tmp2) - elif src.kind in signedIntegers and dst.kind in unsignedIntegers: - # cast signed to unsigned integer of same size - # unsignedVal = (offset +% signedVal +% 1) and offset - let offset = (1 shl (src_size * 8)) - 1 - c.gABx(n, opcLdConst, tmp2, mkIntLit(offset)) - c.gABx(n, opcLdConst, dest, mkIntLit(offset+1)) - c.gABC(n, opcAddu, tmp3, tmp, dest) - c.gABC(n, opcNarrowU, tmp3, TRegister(src_size*8)) - c.gABC(n, opcBitandInt, dest, tmp3, tmp2) - else: - c.gABC(n, opcAsgnInt, dest, tmp) + c.gABC(n, opcAsgnInt, dest, tmp) + if dst_size != sizeof(BiggestInt): # don't do anything on biggest int types + if dst.kind in signedIntegers: # we need to do sign extensions + if dst_size <= src_size: + # Sign extension can be omitted when the size increases. + c.gABC(n, opcSignExtend, dest, TRegister(dst_size*8)) + elif dst.kind in unsignedIntegers: + if src.kind in signedIntegers or dst_size < src_size: + # Cast from signed to unsigned always needs narrowing. Cast + # from unsigned to unsigned only needs narrowing when target + # is smaller than source. + c.gABC(n, opcNarrowU, dest, TRegister(dst_size*8)) c.freeTemp(tmp) - c.freeTemp(tmp2) - c.freeTemp(tmp3) elif src_size == dst_size and src.kind in allowedIntegers and dst.kind in {tyFloat, tyFloat32, tyFloat64}: let tmp = c.genx(n[1]) diff --git a/tests/vm/tcastint.nim b/tests/vm/tcastint.nim index 437342a74b..c64dbc666e 100644 --- a/tests/vm/tcastint.nim +++ b/tests/vm/tcastint.nim @@ -2,6 +2,8 @@ discard """ output: "OK" """ +import macros + type Dollar = distinct int XCoord = distinct int32 @@ -112,6 +114,130 @@ proc test() = doAssert(not compiles(cast[uint32](I8))) doAssert(not compiles(cast[uint64](I8))) +const prerecordedResults = [ + # cast to char + "\0", "\255", + "\0", "\255", + "\0", "\255", + "\0", "\255", + "\0", "\255", + "\128", "\127", + "\0", "\255", + "\0", "\255", + "\0", "\255", + # cast to uint8 + "0", "255", + "0", "255", + "0", "255", + "0", "255", + "0", "255", + "128", "127", + "0", "255", + "0", "255", + "0", "255", + # cast to uint16 + "0", "255", + "0", "255", + "0", "65535", + "0", "65535", + "0", "65535", + "65408", "127", + "32768", "32767", + "0", "65535", + "0", "65535", + # cast to uint32 + "0", "255", + "0", "255", + "0", "65535", + "0", "4294967295", + "0", "4294967295", + "4294967168", "127", + "4294934528", "32767", + "2147483648", "2147483647", + "0", "4294967295", + # cast to uint64 + "0", "255", + "0", "255", + "0", "65535", + "0", "4294967295", + "0", "18446744073709551615", + "18446744073709551488", "127", + "18446744073709518848", "32767", + "18446744071562067968", "2147483647", + "9223372036854775808", "9223372036854775807", + # cast to int8 + "0", "-1", + "0", "-1", + "0", "-1", + "0", "-1", + "0", "-1", + "-128", "127", + "0", "-1", + "0", "-1", + "0", "-1", + # cast to int16 + "0", "255", + "0", "255", + "0", "-1", + "0", "-1", + "0", "-1", + "-128", "127", + "-32768", "32767", + "0", "-1", + "0", "-1", + # cast to int32 + "0", "255", + "0", "255", + "0", "65535", + "0", "-1", + "0", "-1", + "-128", "127", + "-32768", "32767", + "-2147483648", "2147483647", + "0", "-1", + # cast to int64 + "0", "255", + "0", "255", + "0", "65535", + "0", "4294967295", + "0", "-1", + "-128", "127", + "-32768", "32767", + "-2147483648", "2147483647", + "-9223372036854775808", "9223372036854775807", +] + +proc free_integer_casting() = + # cast from every integer type to every type and ensure same + # behavior in vm and execution time. + macro bar(arg: untyped) = + result = newStmtList() + var i = 0 + for it1 in arg: + let typA = it1[0] + for it2 in arg: + let lowB = it2[1] + let highB = it2[2] + let castExpr1 = nnkCast.newTree(typA, lowB) + let castExpr2 = nnkCast.newTree(typA, highB) + let lit1 = newLit(prerecordedResults[i*2]) + let lit2 = newLit(prerecordedResults[i*2+1]) + result.add quote do: + doAssert($(`castExpr1`) == `lit1`) + doAssert($(`castExpr2`) == `lit2`) + i += 1 + + bar([ + (char, '\0', '\255'), + (uint8, 0'u8, 0xff'u8), + (uint16, 0'u16, 0xffff'u16), + (uint32, 0'u32, 0xffffffff'u32), + (uint64, 0'u64, 0xffffffffffffffff'u64), + (int8, 0x80'i8, 0x7f'i8), + (int16, 0x8000'i16, 0x7fff'i16), + (int32, 0x80000000'i32, 0x7fffffff'i32), + (int64, 0x8000000000000000'i64, 0x7fffffffffffffff'i64) + ]) proc test_float_cast = @@ -158,9 +284,11 @@ proc test_float32_cast = test() test_float_cast() test_float32_cast() +free_integer_casting() static: test() test_float_cast() test_float32_cast() + free_integer_casting() echo "OK" From 2334680b3d6ee025b8c2560d591811cbda3eb7cf Mon Sep 17 00:00:00 2001 From: Kaushal Modi Date: Mon, 10 Jun 2019 13:59:51 -0400 Subject: [PATCH 21/25] Use TMPDIR env var if available to get the temp dir name (#11443) [bugfix] Additionally, use normalizePathEnd to suffix the dir name with "/" or "\" as appropriate for the current OS. Fixes https://github.com/nim-lang/Nim/issues/11439. --- lib/pure/os.nim | 13 ++++++++----- tests/stdlib/tos.nim | 12 ++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index aa58fea735..79a24662db 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -798,13 +798,16 @@ proc getTempDir*(): string {.rtl, extern: "nos$1", ## * `expandTilde proc <#expandTilde,string>`_ ## * `getCurrentDir proc <#getCurrentDir>`_ ## * `setCurrentDir proc <#setCurrentDir,string>`_ - const tempDirDefault = "/tmp/" + const tempDirDefault = "/tmp" + result = tempDirDefault when defined(tempDir): const tempDir {.strdefine.}: string = tempDirDefault - return tempDir - elif defined(windows): return string(getEnv("TEMP")) & "\\" - elif defined(android): return getHomeDir() - else: return tempDirDefault + result = tempDir + elif defined(windows): result = string(getEnv("TEMP")) + elif defined(android): result = getHomeDir() + else: + if existsEnv("TMPDIR"): result = string(getEnv("TMPDIR")) + normalizePathEnd(result, trailingSep=true) proc expandTilde*(path: string): string {. tags: [ReadEnvEffect, ReadIOEffect].} = diff --git a/tests/stdlib/tos.nim b/tests/stdlib/tos.nim index 23fa4d098a..2d69332fcf 100644 --- a/tests/stdlib/tos.nim +++ b/tests/stdlib/tos.nim @@ -333,3 +333,15 @@ block ospaths: doAssert joinPath("", "lib") == "lib" doAssert joinPath("", "/lib") == unixToNativePath"/lib" doAssert joinPath("usr/", "/lib") == unixToNativePath"usr/lib" + +block getTempDir: + block TMPDIR: + # TMPDIR env var is not used if either of these are defined. + when not (defined(tempDir) or defined(windows) or defined(android)): + if existsEnv("TMPDIR"): + let origTmpDir = getEnv("TMPDIR") + putEnv("TMPDIR", "/mytmp") + doAssert getTempDir() == "/mytmp/" + putEnv("TMPDIR", origTmpDir) + else: + doAssert getTempDir() == "/tmp/" From f8c8e319bcf093a919c9e03297f15eb7c1a0e97b Mon Sep 17 00:00:00 2001 From: Kaushal Modi Date: Mon, 10 Jun 2019 14:52:56 -0400 Subject: [PATCH 22/25] Ensure that koch-built nim exe has +x perm for u/g/others [bugfix] (#11444) Fixes https://github.com/nim-lang/Nim/issues/11427. --- koch.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/koch.nim b/koch.nim index a2c1f16736..9f2e232904 100644 --- a/koch.nim +++ b/koch.nim @@ -111,7 +111,7 @@ proc overwriteFile(source, dest: string) = proc copyExe(source, dest: string) = safeRemove(dest) copyFile(dest=dest, source=source) - inclFilePermissions(dest, {fpUserExec}) + inclFilePermissions(dest, {fpUserExec, fpGroupExec, fpOthersExec}) const compileNimInst = "tools/niminst/niminst" From ced0527ae334439a10e1719d1eccb727c19dc781 Mon Sep 17 00:00:00 2001 From: jiro Date: Tue, 11 Jun 2019 04:00:55 +0900 Subject: [PATCH 23/25] streams: change error message of `openFileStream` (#11438) [feature] --- lib/pure/streams.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index f1a6a6aeb8..28d9d7612f 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -1241,7 +1241,7 @@ when not defined(js): if open(f, filename, mode, bufSize): return newFileStream(f) else: - raise newEIO("cannot open file\n") + raise newEIO("cannot open file stream: " & filename) when false: type From 51ac2e67bf53f299b3ca54614ef62afc021323bb Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Tue, 11 Jun 2019 08:58:11 +0200 Subject: [PATCH 24/25] newruntime: added a basic table test --- tests/destructor/tsimpletable.nim | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/destructor/tsimpletable.nim diff --git a/tests/destructor/tsimpletable.nim b/tests/destructor/tsimpletable.nim new file mode 100644 index 0000000000..36546b9f6a --- /dev/null +++ b/tests/destructor/tsimpletable.nim @@ -0,0 +1,24 @@ +discard """ + cmd: '''nim c --newruntime $file''' + output: '''(field: "value") +3 3 new: 0''' +""" + +import core / allocators +import system / ansi_c + +import tables + +type + Node = ref object + field: string + +proc main = + var w = newTable[string, owned Node]() + w["key"] = Node(field: "value") + echo w["key"][] + +main() + +let (a, d) = allocCounters() +discard cprintf("%ld %ld new: %ld\n", a, d, allocs) From 639e9a7aa9bed6d2379820e64f3b112241843be2 Mon Sep 17 00:00:00 2001 From: Miran Date: Tue, 11 Jun 2019 11:43:54 +0200 Subject: [PATCH 25/25] [other] test 6 more nimble packages (#11464) --- testament/categories.nim | 9 +++------ testament/important_packages.nim | 11 ++++++++--- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/testament/categories.nim b/testament/categories.nim index 4fddeb5548..3db90d15f1 100644 --- a/testament/categories.nim +++ b/testament/categories.nim @@ -474,11 +474,7 @@ iterator listPackages(): tuple[name, url, cmd: string, hasDeps: bool] = for n, cmd, hasDeps, url in important_packages.packages.items: let cmd = if cmd.len == 0: defaultCmd else: cmd if url.len != 0: - if hasDeps: - # use url instead of name, so we can do 'nimble install' - yield (url, url, cmd, hasDeps) - else: - yield (n, url, cmd, hasDeps) + yield (n, url, cmd, hasDeps) else: var found = false for package in packageList.items: @@ -515,7 +511,8 @@ proc testNimblePackages(r: var TResults, cat: Category) = let buildPath = packagesDir / name if not existsDir(buildPath): if hasDep: - let (nimbleCmdLine, nimbleOutput, nimbleStatus) = execCmdEx2("nimble", ["install", "-y", name]) + let installName = if url.len != 0: url else: name + let (nimbleCmdLine, nimbleOutput, nimbleStatus) = execCmdEx2("nimble", ["install", "-y", installName]) if nimbleStatus != QuitSuccess: let message = "nimble install failed:\n$ " & nimbleCmdLine & "\n" & nimbleOutput r.addResult(test, targetC, "", message, reInstallFailed) diff --git a/testament/important_packages.nim b/testament/important_packages.nim index fbd97c96d6..049b50e72e 100644 --- a/testament/important_packages.nim +++ b/testament/important_packages.nim @@ -24,6 +24,7 @@ pkg "comprehension", "", false, "https://github.com/alehander42/comprehension" pkg "criterion" pkg "dashing", "nim c tests/functional.nim" pkg "docopt" +pkg "easygl", "nim c -o:egl -r src/easygl.nim", true, "https://github.com/jackmott/easygl" pkg "fragments", "nim c -r fragments/dsl.nim" pkg "gara" pkg "glob" @@ -49,17 +50,17 @@ pkg "nimfp", "nim c -o:nfp -r src/fp.nim", true pkg "nimgame2", "nim c nimgame2/nimgame.nim", true pkg "nimgen", "nim c -o:nimgenn -r src/nimgen/runcfg.nim", true # pkg "nimlsp", "", true -# pkg "nimly", "nim c -r tests/test_nimly", true +pkg "nimly", "nim c -r tests/test_nimly", true # pkg "nimongo", "nimble test_ci", true pkg "nimpy", "nim c -r tests/nimfrompy.nim" pkg "nimquery" pkg "nimsl", "", true pkg "nimsvg" pkg "nimx", "nim c --threads:on test/main.nim", true -pkg "norm", "nim c -o:normm src/norm.nim" +# pkg "norm", "nim c -o:normm src/norm.nim", true pkg "npeg" pkg "ormin", "nim c -o:orminn ormin.nim", true -#pkg "parsetoml" +pkg "parsetoml" pkg "patty" pkg "plotly", "nim c examples/all.nim", true pkg "protobuf", "nim c -o:protobuff -r src/protobuf.nim", true @@ -68,11 +69,15 @@ pkg "result", "nim c -r result.nim" pkg "rosencrantz", "nim c -o:rsncntz -r rosencrantz.nim" pkg "sdl1", "nim c -r src/sdl.nim" pkg "sdl2_nim", "nim c -r sdl2/sdl.nim" +pkg "snip", "", false, "https://github.com/genotrance/snip" pkg "stint", "nim c -o:stintt -r stint.nim" pkg "strunicode", "nim c -r src/strunicode.nim", true +pkg "telebot", "nim c -o:tbot -r telebot.nim", true pkg "tiny_sqlite" pkg "unicodedb" pkg "unicodeplus", "", true pkg "unpack" +pkg "with" +# pkg "winim", "", true pkg "yaml" pkg "zero_functional", "nim c -r test.nim"