mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-22 00:41:28 +00:00
Merge remote-tracking branch 'upstream/devel' into version-0-20
This commit is contained in:
12
.github/FUNDING.yml
vendored
Normal file
12
.github/FUNDING.yml
vendored
Normal file
@@ -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
|
||||
263
changelog.md
263
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
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
import idents, lexer, lineinfos, llstream, options, msgs, strutils,
|
||||
pathutils
|
||||
from os import changeFileExt
|
||||
from sequtils import delete
|
||||
|
||||
const
|
||||
MaxLineLen = 80
|
||||
LineCommentColumn = 30
|
||||
|
||||
type
|
||||
SplitKind = enum
|
||||
@@ -24,6 +24,12 @@ type
|
||||
SemicolonKind = enum
|
||||
detectSemicolonKind, useSemicolon, dontTouch
|
||||
|
||||
LayoutToken = enum
|
||||
ltSpaces, ltNewline, ltTab,
|
||||
ltComment, ltLit, ltKeyword, ltExportMarker, ltIdent,
|
||||
ltOther, ltOpr,
|
||||
ltBeginSection, ltEndSection
|
||||
|
||||
Emitter* = object
|
||||
config: ConfigRef
|
||||
fid: FileIndex
|
||||
@@ -33,7 +39,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
|
||||
@@ -50,21 +57,72 @@ 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 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
|
||||
if fileExists(outFile) and readFile(outFile.string) == em.content:
|
||||
|
||||
var content = newStringOfCap(16_000)
|
||||
var maxLhs = 0
|
||||
var lineLen = 0
|
||||
var lineBegin = 0
|
||||
for i in 0..em.tokens.high:
|
||||
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"
|
||||
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 =
|
||||
@@ -79,9 +137,36 @@ proc calcCol(em: var Emitter; s: string) =
|
||||
dec i
|
||||
inc em.col
|
||||
|
||||
template wr(x) =
|
||||
em.content.add x
|
||||
proc wr(em: var Emitter; x: string; lt: LayoutToken) =
|
||||
em.tokens.add x
|
||||
em.kinds.add lt
|
||||
inc em.col, x.len
|
||||
assert em.tokens.len == em.kinds.len
|
||||
|
||||
proc wrNewline(em: var Emitter) =
|
||||
em.tokens.add "\L"
|
||||
em.kinds.add ltNewline
|
||||
em.col = 0
|
||||
|
||||
proc wrSpaces(em: var Emitter; spaces: int) =
|
||||
if spaces > 0:
|
||||
wr(em, strutils.repeat(' ', spaces), ltSpaces)
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
@@ -89,13 +174,17 @@ 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}
|
||||
|
||||
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)
|
||||
@@ -106,54 +195,109 @@ 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:
|
||||
removeSpaces em
|
||||
wrNewline(em)
|
||||
em.col = 0
|
||||
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
|
||||
|
||||
proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
|
||||
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:
|
||||
wrNewline em
|
||||
else:
|
||||
if a > lastIndent:
|
||||
b += em.indWidth
|
||||
lastIndent = a
|
||||
elif a < lastIndent:
|
||||
b -= em.indWidth
|
||||
lastIndent = a
|
||||
wrNewline em
|
||||
wrSpaces em, col + b
|
||||
wr em, stripped, ltComment
|
||||
inc i
|
||||
|
||||
template endsInWhite(em): bool =
|
||||
em.content.len == 0 or em.content[em.content.high] in {' ', '\L'}
|
||||
template endsInAlpha(em): bool =
|
||||
em.content.len > 0 and em.content[em.content.high] in SymChars+{'_'}
|
||||
proc lastChar(s: string): char =
|
||||
result = if s.len > 0: s[s.high] else: '\0'
|
||||
|
||||
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)
|
||||
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):
|
||||
wr(" ")
|
||||
if em.lineSpan == 0 and max(em.col, LineCommentColumn) + lit.len <= MaxLineLen:
|
||||
for i in 1 .. LineCommentColumn - em.col: wr(" ")
|
||||
wr lit
|
||||
wrTab em
|
||||
emitMultilineComment(em, lit, col)
|
||||
|
||||
proc emitTok*(em: var Emitter; L: TLexer; tok: TToken) =
|
||||
template wasExportMarker(em): bool =
|
||||
em.kinds.len > 0 and em.kinds[^1] == ltExportMarker
|
||||
|
||||
if tok.tokType == tkComment and tok.literal.startsWith("#!nimpretty"):
|
||||
case tok.literal
|
||||
of "#!nimpretty off":
|
||||
inc em.keepIndents
|
||||
wr("\L")
|
||||
wrNewline em
|
||||
em.lastLineNumber = tok.line + 1
|
||||
of "#!nimpretty on":
|
||||
dec em.keepIndents
|
||||
em.lastLineNumber = tok.line
|
||||
wr("\L")
|
||||
#for i in 1 .. tok.indent: wr " "
|
||||
wr tok.literal
|
||||
wrNewline em
|
||||
wr em, tok.literal, ltComment
|
||||
em.col = 0
|
||||
em.lineSpan = 0
|
||||
return
|
||||
@@ -163,11 +307,15 @@ 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.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
|
||||
@@ -186,51 +334,48 @@ 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("\L")
|
||||
for i in 2..tok.line - em.lastLineNumber: wr("\L")
|
||||
em.col = 0
|
||||
for i in 1..em.indentLevel:
|
||||
wr(" ")
|
||||
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(" ")
|
||||
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(" ")
|
||||
wrSpace em
|
||||
|
||||
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(" ")
|
||||
wrSpace em
|
||||
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)
|
||||
wrSpace em
|
||||
of tkSemicolon, tkComma:
|
||||
wr(TokTypeToStr[tok.tokType])
|
||||
wr(em, TokTypeToStr[tok.tokType], ltOther)
|
||||
rememberSplit(splitComma)
|
||||
wr(" ")
|
||||
wrSpace em
|
||||
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:
|
||||
wrSpace em
|
||||
wr(em, TokTypeToStr[tok.tokType], ltOther)
|
||||
rememberSplit(splitParLe)
|
||||
of tkParRi,
|
||||
tkBracketRi, tkCurlyRi,
|
||||
@@ -238,33 +383,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: wrSpace(em)
|
||||
wr(em, TokTypeToStr[tok.tokType], ltOther)
|
||||
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 ["<", ">", "<=", ">=", "==", "!="]:
|
||||
# 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: 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(" ")
|
||||
wrSpace(em)
|
||||
of tkAccent:
|
||||
if not em.inquote and endsInAlpha(em): wr(" ")
|
||||
wr(TokTypeToStr[tok.tokType])
|
||||
if not em.inquote and endsInAlpha(em): wrSpace(em)
|
||||
wr(em, TokTypeToStr[tok.tokType], ltOther)
|
||||
em.inquote = not em.inquote
|
||||
of tkComment:
|
||||
if not preventComment:
|
||||
@@ -272,36 +417,43 @@ 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}: wrSpace(em)
|
||||
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): wrSpace(em)
|
||||
wr em, lit, ltIdent
|
||||
|
||||
em.lastTok = tok.tokType
|
||||
em.lastTokWasTerse = lastTokWasTerse
|
||||
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) =
|
||||
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
|
||||
|
||||
@@ -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,13 +89,20 @@ 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:
|
||||
while p.tok.tokType == tkComment:
|
||||
rawGetTok(p.lex, p.tok)
|
||||
emitTok(p.em, p.lex, p.tok)
|
||||
@@ -106,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
|
||||
@@ -119,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 = "") =
|
||||
@@ -382,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)
|
||||
@@ -393,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) =
|
||||
@@ -828,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 =
|
||||
@@ -908,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:
|
||||
@@ -920,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))
|
||||
@@ -999,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)
|
||||
@@ -1035,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
|
||||
@@ -1057,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)
|
||||
@@ -1072,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
|
||||
|
||||
@@ -1235,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)
|
||||
@@ -1694,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)
|
||||
@@ -2185,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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
12
doc/nimc.rst
12
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 <manual.html#when-statement>`_ and
|
||||
`defined proc <system.html#defined>`_. 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
|
||||
|
||||
@@ -17,7 +17,7 @@ customize this style sheet.
|
||||
*/
|
||||
|
||||
/*
|
||||
Modified for the Nimrod Documenation by
|
||||
Modified for the Nim Documenation by
|
||||
Andreas Rumpf
|
||||
*/
|
||||
|
||||
|
||||
2
koch.nim
2
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"
|
||||
|
||||
@@ -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``.
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -798,12 +798,16 @@ proc getTempDir*(): string {.rtl, extern: "nos$1",
|
||||
## * `expandTilde proc <#expandTilde,string>`_
|
||||
## * `getCurrentDir proc <#getCurrentDir>`_
|
||||
## * `setCurrentDir proc <#setCurrentDir,string>`_
|
||||
const tempDirDefault = "/tmp"
|
||||
result = tempDirDefault
|
||||
when defined(tempDir):
|
||||
const tempDir {.strdefine.}: string = nil
|
||||
return tempDir
|
||||
elif defined(windows): return string(getEnv("TEMP")) & "\\"
|
||||
elif defined(android): return getHomeDir()
|
||||
else: return "/tmp/"
|
||||
const tempDir {.strdefine.}: string = 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].} =
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
--define: nimnoio
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
--define: nimpretty
|
||||
--define: nimpretty2
|
||||
--define: nimOldCaseObjects
|
||||
|
||||
@@ -366,3 +366,46 @@ 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")
|
||||
|
||||
|
||||
# bug #10177
|
||||
|
||||
proc foo * () =
|
||||
discard
|
||||
|
||||
proc foo* [T]() =
|
||||
discard
|
||||
|
||||
|
||||
# bug #10159
|
||||
|
||||
proc fun() =
|
||||
discard
|
||||
|
||||
proc main() =
|
||||
echo "foo"; echo "bar";
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
@@ -375,3 +375,47 @@ 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")
|
||||
|
||||
|
||||
# bug #10177
|
||||
|
||||
proc foo*() =
|
||||
discard
|
||||
|
||||
proc foo*[T]() =
|
||||
discard
|
||||
|
||||
|
||||
# bug #10159
|
||||
|
||||
proc fun() =
|
||||
discard
|
||||
|
||||
proc main() =
|
||||
echo "foo"; echo "bar";
|
||||
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
|
||||
|
||||
73
nimpretty/tests/expected/wrong_ind.nim
Normal file
73
nimpretty/tests/expected/wrong_ind.nim
Normal file
@@ -0,0 +1,73 @@
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
# 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
|
||||
73
nimpretty/tests/wrong_ind.nim
Normal file
73
nimpretty/tests/wrong_ind.nim
Normal file
@@ -0,0 +1,73 @@
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
# 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
24
tests/destructor/tsimpletable.nim
Normal file
24
tests/destructor/tsimpletable.nim
Normal file
@@ -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)
|
||||
@@ -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))
|
||||
|
||||
@@ -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/"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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]' \
|
||||
|
||||
Reference in New Issue
Block a user